1

我有一台服务器通过NetworkStream.Read.

应用协议为:

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

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

我想这样的客户端消息足够短,可以放入 tcp/ip 层上的一个数据包中——但是会不会有某种碎片或随机的呢?

NetworkStream.DataAvailable防御这种情况的正确属性是什么?

在平稳运行了几个小时后,我有时会遇到奇怪的错误和连接丢失,这就是类似的情况。

提前致谢。

4

2 回答 2

1

简短的回答:

绝对不能保证您将在一次调用中接收到整个数据包Read,即使数据包是在一次Write调用中发送的,并且它小于网络 MTU,即使您实际上正在发送到环回接口/从环回接口读取. 你不能对这种行为做任何事情。

文档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
    }
}
于 2011-03-27T00:47:55.750 回答
1

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

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

请参阅文档

The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.

See this link on how to properly read from streams

Try something like this instead: (pass in a 128 length byte array)

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;
        }
    }
于 2011-03-27T00:47:58.547 回答