2012-04-13 100 views
2

我们正在Windows Embedded CE 6平台上开发.NET CF 3.5应用程序。我们试图在.NET中实现一个小型(HTTP 1.0)Web服务器,该服务器应该提供WebApp并响应简单的REST请求。通过更改SOMAXCONN来增加Windows CE中的最大积压?

我们的实施遵循此MSDN文章中显示的模式:http://msdn.microsoft.com/en-us/library/aa446537.aspx。我们使用TCP侦听套接字,异步回调与BeginAccept,EndAccept,BeginRecieve和EndReceive结合使用。

侦听端口上的传入连接由异步接受回调处理。 (参见http://msdn.microsoft.com/en-us/library/5bb431f9.aspx)。 通过调用EndAccept方法,在此异步接受回调中,我们告诉侦听端口将连接移交给一个新的套接字并释放该端口,以便侦听端口可以接受新的传入连接请求。已接受的请求在自己的线程中处理(因为它是在异步回调中处理的)。

我们已经尝试尽量缩短BeginAccept和EndAccept之间的时间。因为在调用BeginAccept和EndAccept之间的这段时间内,传入的连接请求被放置在侦听套接字的积压队列中。这个队列的长度可以通过所谓的backlog参数来配置 - 这个参数有一个依赖plattform的最大值。如果积压队列耗尽,则在三次握手期间拒绝新的tcp连接请求(客户端/浏览器获取RST作为对syn的响应)。

现在我们碰到了这个问题,大多数现代浏览器如Firefox,Chrome,Safari等使用最多15个(或更多)的并发连接从服务器加载数据(每个主机的最大并发连接数可以在Firefox中使用about:config - > network.http.max-connections-per-server)进行配置。加载页面时,浏览器根据需要加载的资源数量(例如图像,javascript或css文件)建立15个连接。

.NET CF socket.listen方法(请参阅http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.listen.aspx)允许定义积压编号。
根据我们的理解,我们应该有一个积压超过15,例如, 20左右,因为所有连接请求都是由浏览器同时触发的,所以我们的小型网络服务器受到了15个同时连接请求的冲击。队列大小太小会导致TCP连接中止,因为在侦听套接字可以接受所有连接之前,并不是所有传入连接都可以是队列。在Firebug或Chrome中,这些请求显示为“中止”。 所以我们通过socket.listen(20)将我们的积压增加到了20,希望一切都会好起来,并且准备好承受最贪婪的浏览器。

问题是,socket.listen()调用中的backlog参数默认设置为SOMAXXCON(在我们的例子中最多5个连接)。设置一个高于这个值的数字并没有效果。当浏览器建立例如有16个并发套接字连接,有些丢失,这是因为某些套接字不适合5的积压队列,而TCP连接从网络服务器获取TCP-RST - 而且网页上缺少一些资源。

有没有办法在Windows Embedded CE 6.0中更改SOMAXXCON? (我们能够改变平台图像 - 利用plattform生成器)。或者我们对这个问题的理解有错误吗?

我们连接,我们目前正在使用的源代码:

public class StateObject 
    { 
     // Client socket. 
     public Socket workSocket = null; 
     // Size of receive buffer. 
     public const int BufferSize = 1024; 
     // Receive buffer. 
     public byte[] buffer = new byte[BufferSize]; 
     // Received data string. 
     public StringBuilder sb = new StringBuilder(); 
    } 

public void StartListening() 
    { 
     logger.Debug("Started Listening at : " + this.listeninghostIp + ":" + this.listeningport); 
     IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(this.listeninghostIp), Convert.ToInt32(this.listeningport)); 
     listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 

     listener.Bind(localEP); 
     listener.Listen(10); 
     ThreadPool.QueueUserWorkItem(new WaitCallback(CheckForConnections)); 
    } 

public void CheckForConnections() 
    { 
     try 
     { 
      logger.Debug("listening successfully started! Waiting for incoming connections..."); 
      listener.BeginAccept(new AsyncCallback(acceptCallback), listener); 
      } 
     catch (Exception ex) 
     { 
      logger.Error("Exception Occured while starting Listening : " + ex.Message.ToString()); 
     } 
    } 

private void acceptCallback(IAsyncResult ar) 
    { 
     try 
     { 

      Socket listener = (Socket)ar.AsyncState; 
      listener.BeginAccept(new AsyncCallback(acceptCallback), listener); 
      Socket handler = listener.EndAccept(ar); 
      StateObject state = new StateObject(); 
      state.workSocket = handler; 
      handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
     new AsyncCallback(ReadCallback), state); 

      logger.Debug("listening socket accepted connection..."); 

     } 
     catch (Exception ex) 
     { 
      logger.Error("Error on acceptCallback. Error: " + ex.Message); 
     } 

public void ReadCallback(IAsyncResult ar) 
    { 
     String content = String.Empty; 

     StateObject state = (StateObject)ar.AsyncState; 
     Socket handler = state.workSocket; 
     int bytesRead = handler.EndReceive(ar); 

     if (bytesRead > 0) 
     { 
      state.sb.Append(Encoding.ASCII.GetString(
      state.buffer, 0, bytesRead)); 
     } 
     ClientConnectionFactory.createConnection(ar.AsyncState); 
} 

回答

-1

我觉得你的方向错了路 - 你绝对可以处理这个sceanrio不改变积压请求数。

客户端请求进入端口80,但响应不会返回到端口80上的客户端。这意味着您可以使用异步套接字处理来接收请求,然后将其传递给解析并以这种方式回复后续请求不会等待完整处理先前的请求。我们在Padarn网络服务器中使用这种技术,并且在处理来自单个客户端浏览器的多个请求或甚至来自多个同时客户端的多个请求时没有问题。

+0

嗨克里斯,感谢您的快速响应,我已更新我的文章,以提供更多的见解,并显示/验证我们对这个特定事件的理解!根据我的理解,我们已经使用异步套接字处理。 – Chris 2012-04-14 15:44:53

+0

我必须去看看Padarn来源,看看我们使用的模式是什么样子,但我确实知道我们没有调整积压,并且我们没有遇到任何问题请求,甚至来自多个客户端,并且当一个页面使用很多请求时,需要很多请求到服务器来呈现页面。我会尽快看到能否实现,但可能是星期一。 – ctacke 2012-04-14 16:20:58

+0

请你首先回答问题,然后你可以提出建议,一个建议,尤利只是一个评论。 – 2017-07-07 08:30:14