2013-04-03 116 views
3

我有一个TCP服务器异步侦听传入连接。如果只有一个客户端连接,一切正常。但是,如果有两个或更多个连接,则服务器不会收到第一条消息。当我调试ReceiveCallback函数,我可以看到服务器获取消息的长度,但不是数据。即如果我连接两个客户端并尝试发送第一条消息:“hello”,服务器将得到:received = 5;缓冲区=/0/0/0/0/0,因此不显示任何内容。在同一客户端的第二条消息中,服务器获取数据。用于多个客户端的异步TCP服务器

这就是我的服务器看起来像:

 private void StartServer() 
    { 
     try 
     { 
      serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      serverSocket.Bind(new IPEndPoint(IPAddress.Any, 3333)); 
      serverSocket.Listen(100); 
      serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); 

     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); 
     } 
    } 


    private void AcceptCallback(IAsyncResult ar) 
    { 
     try 
     { 
      Socket clientSocket = serverSocket.EndAccept(ar); 
      clientSocketList.Add(clientSocket); 
      AppendToTextBox("ClientConnected"); 
      clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), clientSocket); 
      serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); 

     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); 
     } 
    } 


     private void ReceiveCallback(IAsyncResult ar) 
    { 
     try 
     { 
      int received = 0; 
      Socket current = (Socket)ar.AsyncState; 
      received = current.EndReceive(ar); 
      byte[] data = new byte[received]; 

      if (received == 0) 
      { 
       return; 
      } 

      Array.Copy(buffer, data, received); 
      string text = Encoding.ASCII.GetString(data); 

      AppendToTextBox(text); 
      buffer = null; 
      Array.Resize(ref buffer, current.ReceiveBufferSize); 

      current.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), current); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); 
     } 
    } 

回答

2

看到http://msdn.microsoft.com/en-us/library/dxkwh6zw.aspx

比如你想改变你的代码,以便它分配一个新的每次调用BeginReceive时间缓冲:

 Socket clientSocket = serverSocket.EndAccept(ar); 
     clientSocketList.Add(clientSocket); 
     AppendToTextBox("ClientConnected"); 
     var buffer = new byte[BUFFER_LENGTH]; // <--- 
     clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), clientSocket); 
     serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); 

每个客户端必须有一个缓冲区。否则,一个客户端可以覆盖另一个客户端使用的缓冲区。

+1

您可能会希望为'BeginReceive'的'state'参数使用多于'clientSocket',因为您的'ReceiveCallback'最有可能需要使用'buffer'来解析接收到的数据。 @Jim包含的链接通过使用类的实例作为'state'参数来演示解决此问题的方法。 – Spooky 2013-08-09 17:58:18