在NetworkStream异步读取回调中读取部分消息

时间:2013-05-23 14:43:01

标签: c# sockets asynchronous stream

我们有一个C#应用程序,它使用一个相对简单的协议通过TCP / IP与设备通信,该协议由一系列消息组成,这些消息具有固定大小的头和可变长度的有效负载。标头包含有效负载的长度。

最近我们将编程模型从同步转换为异步,现在有一个有趣的问题:如何处理部分接收的消息。

同步代码

public void ReceiveMessage(NetworkStream stream)
{
    // Read the header from the stream
    MessageHeader header = stream.ReadHeader();

    int payloadBytesRead = 0;
    byte[] buffer = new byte[header.PayloadSize];

    // Keep reading from the stream until the payload
    // is fully extracted
    while (payloadBytesRead < header.PayloadSize)
    {
        payloadBytesRead += stream.Read(buffer, payloadBytesRead, header.PayloadSize - payloadBytesRead);
    }

    MessagePayload = new MessagePayload(buffer);

    // Do something with the message here
    // ...

}

其中ReadHeaderNetworkStream上的一种扩展方法,用于从流中提取固定大小的标头。

异步版本问题

在我们使用BeginReadEndRead的异步版本中,有可能在缓冲区中使用部分接收的消息调用读取回调。由于在之后调用了回调,因此从流中提取数据,因此无法在流中留下部分消息以进行下一次回调。但是,我们必须将此部分数据保留到下一个回调,以便以后进行处理。

似乎唯一的解决方案是将部分数据字节复制到不同的缓冲区,或者在调用下一个BeginRead之前将它们移到接收缓冲区的底部。这是正确的,还是有更常用的技术来处理这种情况?

0 个答案:

没有答案