关于异步套接字操作和消息框架的.NET问题

And*_*rew 9 .net c# sockets asyncsocket

我一直在寻找有关如何处理TCP消息框架的示例.我看到许多示例,其中NetworkStreams被传递到StreamReader或StreamWriter对象,然后使用ReadLine或WriteLine方法来处理'\n'分隔的消息.我的应用程序协议包含以'\n'结尾的消息,因此NetworkStream似乎是最佳选择.但是,我找不到任何关于正确处理所有这些与异步套接字相结合的方法的具体示例.当下面调用ReceiveCallback()时,如何实现NetworkStream和StreamReader类来处理消息框架?根据我所读到的内容,我可以在一次接收中获取一条消息的一部分,并在下一次接收时获取剩余的消息(包括'\n').这是否意味着我可以得到一条消息的结尾和下一条消息的一部分?当然,必须有一种更简单的方法来处理这个问题.

我有以下代码:

    private void StartRead(Socket socket)
    {
        try
        {
            StateObject state = new StateObject();
            state.AsyncSocket = socket;

            socket.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
        }
        catch (SocketException)
        {
            m_Socket.Shutdown(SocketShutdown.Both);
            Disconnect();
        }
    }

    private void ReceiveCallback(IAsyncResult ar)
    {
        try
        {
            StateObject state = (StateObject)ar.AsyncState;

            int bytes_read = state.AsyncSocket.EndReceive(ar);

            char[] chars = new char[bytes_read + 1];
            System.Text.Decoder decoder = System.Text.Encoding.UTF8.GetDecoder();
            int charLength = decoder.GetChars(state.Buffer, 0, bytes_read, chars, 0);

            String data = new String(chars);

            ParseMessage(data);

            StartRead(state.AsyncSocket);
        }
        catch (SocketException)
        {
            m_Socket.Shutdown(SocketShutdown.Both);
            Disconnect();
        }
    }
Run Code Online (Sandbox Code Playgroud)

C.E*_*uis 1

基本上,您创建一个缓冲区,每次接收数据时,都会将该数据添加到缓冲区并确定是否已收到一条或多条完整消息。

在 和 之间,ReceiveCallbackStartRead不会收到任何异步消息(传入数据将自动在套接字级别进行缓冲),因此它是检查完整消息并将其从缓冲区中删除的理想位置。

所有变化都是可能的,包括接收消息 1 的结尾,加上消息 2,加上消息 3 的开头,所有这些都在一个块中。

我不建议对块进行 UTF8 解码,因为一个 UTF8 字符可能由两个字节组成,如果它们在块之间分割,您的数据可能会损坏。在这种情况下,您可以保留一个字节[]缓冲区(MemoryStream?)并在 0x0A 字节上分割消息。