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

2023-09-04 00:39:06 作者:兜 兜、

我一直在到处找关于如何处理TCP报文帧的例子。我看到NetworkStreams传递到一个StreamReader或StreamWriter对象的例子很多,然后使用输入行或的WriteLine方法'\ N'分隔的消息。我的应用协议包含在结尾的'\ N'这样的NetworkStream似乎是要走的路的消息。但是,我无法找到正确的方式来处理与异步套接字结合这一切的具体例子。当ReceiveCallback()如下叫,我怎么实现的NetworkStream和StreamReader的类来处理消息帧?据我读过,我可能会得到一个消息的一个部分接收并在接下来的消息(包括'\ N')的其余部分领取。这是否意味着我能得到一个消息,下一个消息的一部分的结束?当然,必须有一个更简单的方法来处理这​​个问题。

我有以下的code:

 私人无效StartRead(Socket套接字)
    {
        尝试
        {
            StateObject状态=新StateObject();
            state.AsyncSocket =插座;

            socket.BeginReceive(state.Buffer,0,StateObject.BufferSize,0,新的AsyncCallback(ReceiveCallback),状态);
        }
        赶上(SocketException)
        {
            m_Socket.Shutdown(SocketShutdown.Both);
            断开();
        }
    }

    私人无效ReceiveCallback(IAsyncResult的AR)
    {
        尝试
        {
            StateObject状态=(StateObject)ar.AsyncState;

            INT bytes_read缓存= state.AsyncSocket.EndReceive(AR);

            的char []字符=新的char [bytes_read缓存+ 1];
            System.Text.De codeR德codeR = System.Text.Encoding.UTF8.GetDe codeR();
            INT charLength =去coder.GetChars(state.Buffer,0,bytes_read缓存,字符,0);

            字符串数据=新的String(字符);

            ParseMessage(数据);

            StartRead(state.AsyncSocket);
        }
        赶上(SocketException)
        {
            m_Socket.Shutdown(SocketShutdown.Both);
            断开();
        }
    }
 

解决方案

基本上你创建一个缓冲区,并在每次接收数据的时候,你添加数据到缓冲区,并确定您是否已经收到一个或多个完整的信息。

ReceiveCallback StartRead 您将不会收到任何异步消息(传入的数据将自动在缓冲套接字级别),因此它的检查完全信息,然后从缓存中删除他们的理想之地。

所有变化都是可能的,包括:接收消息1的端部,加上消息2,加消息3的开始时,都在一个组块。

我不建议UTF8解码块,为一个UTF8字符可以由两个字节,如果他们得到的块之间的分割你的数据可能会损坏。你可以保持一个byte [] - 缓冲(?的MemoryStream )和拆分的消息就在这种情况下的0x0A字节

I've been looking everywhere for examples on how to deal with TCP message framing. I see many examples where NetworkStreams are passed into a StreamReader or StreamWriter object and then use ReadLine or WriteLine methods for '\n' delimited messages. My application protocol contains messages ending in '\n' so the NetworkStream seems to be the way to go. However, I can't find any specific examples on the proper way to handle all of this in combination with asynchronous sockets. When ReceiveCallback() is called below, how do I implement the NetworkStream and StreamReader classes to deal with message framing? According to what I've read, I may get part of one message in one receive and the rest of the message (including the '\n') in the next receive. Does this mean I could get the end of one message and part of the next message? Surely, there must be an easier way to handle this.

.NET框架

I have the following code:

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

解决方案

Basically you create a buffer, and each time you receive data, you add that data to the buffer and determine if you have already received one or more full messages.

Between ReceiveCallback and StartRead you won't receive any asynchronous messages (incoming data will automatically be buffered on the socket level) so it's the ideal place to check for full messages and remove them from the buffer.

All variations are possible, including receiving the end of message 1, plus message 2, plus the beginning of message 3, all in one chunk.

I don't recommend UTF8-decoding the chunk, as one UTF8-character may consist of two bytes, and if they get split between chunks your data could be corrupted. You could keep a byte[]-buffer (MemoryStream?) and split messages on the 0x0A byte in that case.