【问题标题】:Async TCP Server for multiple Clients用于多个客户端的异步 TCP 服务器
【发布时间】:2013-03-25 16:17:51
【问题描述】:

我有一个异步侦听传入连接的 TCP 服务器。如果只连接一个客户端,一切正常。但是如果有两个或多个连接,服务器就不会收到第一条消息。当我调试 ReceiveCallback 函数时,我可以看到服务器获取消息的长度,而不是数据。 IE。如果我连接两个客户端并尝试发送第一条消息:“hello”,服务器会得到:received = 5; buffer= /0/0/0/0/0,所以什么都不显示。在同一客户端的第二条消息中,服务器获取数据。

这就是我的服务器的样子:

        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);
        }
    }

【问题讨论】:

    标签: c# sockets asynchronous tcp asynccallback


    【解决方案1】:

    查看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);
    

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

    【讨论】:

    • 对于BeginReceivestate 参数,您可能希望使用更多clientSocket,因为您的ReceiveCallback 很可能需要使用buffer解释收到的数据。 @Jim 包含的链接演示了通过使用类的实例作为state 参数来解决此问题的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-26
    • 2011-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多