从网络流中读取:数据包碎片

时间:2011-03-27 00:37:41

标签: .net tcp tcpclient networkstream fragmentation

我有一台服务器通过NetworkStream.Read管理两个客户端。

申请协议是:

ClientMessage [128字节]→来自服务器的响应[128字节]

现在在服务器端:是否可能,MyTcpClient.GetStream().Read()仅返回< 128字节,虽然来自客户端的所有消息都是128字节长?

我猜这样的客户端消息很短,足以容纳tcp / ip层上的一个数据包 - 但是可能存在某种碎片或随机的情况吗?

NetworkStream.DataAvailable是正确的属性来抵御这个吗?

经过几个小时的平稳运行后,我有时会遇到奇怪的错误和连接丢失,这就是那种情况。

提前致谢。

2 个答案:

答案 0 :(得分:1)

简短回答:

完全无法保证您将在一次Read通话中收到整个数据包,即使该数据包是在Write次通话中发送的,也是较小的比网络MTU,即使你实际上是发送到/从loopback接口读取。你不能对这种行为采取任何行动。

Read的文档明确指出:

  

实施可以自由返回   字节数少于请求的字节数   流的结尾还没有   达到。

可以做的事情会像这样(伪代码)

While (true) {
    Read from stream
    If bytes read == 0 {
        Socket was closed (buffer should be empty here)
        Break
    }
    Append read data to persistent buffer
    While (buffer.Length >= 128) {
        Extract first 128 bytes from buffer (buffer length now reduced by 128)
        Process message
    }
}

答案 1 :(得分:1)

  

是否可能,MyTcpClient.GetStream()。Read()仅返回< 128字节

是。您不能假设您对Read()的调用将返回128个字节。

请参阅docs

  

读入的总字节数   缓冲区。这可能比   请求的字节数,如果那么多   字节当前不可用,或   零(0)如果流的末尾有   已经到达。

有关如何正确阅读流的信息,请参阅this链接

尝试这样的事情:(传入一个128长度的字节数组)

private static void ReadWholeArray (Stream stream, byte[] data)
    {
        int offset=0;
        int remaining = data.Length;
        while (remaining > 0)
        {
            int read = stream.Read(data, offset, remaining);
            if (read <= 0)
                throw new EndOfStreamException 
                    (String.Format("End of stream reached with {0} bytes left to read", remaining));
            remaining -= read;
            offset += read;
        }
    }