C# - NetworkStream.Read - 填充整个缓冲区的正确方法(否则抛出异常)

时间:2015-11-24 14:42:41

标签: c# .net network-programming

NetworkStream.Read method documentation表示在两种情况下它返回零:

  • "如果没有可用于读取的数据,则Read方法返回0。"
  • "如果远程主机关闭连接,并且已收到所有可用数据,则Read方法立即完成并返回零字节。"

还有以下观察:

  

通过调用CanRead属性来检查NetworkStream是否可读。如果您尝试从无法读取的NetworkStream中读取,则会出现IOException。

我对此非常困惑。我怎么知道我可以继续阅读或者我应该停止尝试阅读?

采用以下示例方法:

void Receive(byte[] buffer)
{
    int idx = 0;
    while (idx < buffer.Length)
    {
        if (input.CanRead)
        {
            int read = input.Read(buffer, idx, buffer.Length - idx);

            if (read == 0)
            {
                // ???
            }

            idx += read;
        }
        else
        {
            throw new MyLibConnectionClosedException("Cannot receive because the connection was closed");
        }
    }
}

它应该填满整个缓冲区,否则应抛出异常(如果连接已关闭或丢失)。这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

采用基于证据的方法来确定事实......如果您查看Stream.CopyTo的源代码,它依赖于方法Stream.InternalCopyTo,您将看到以下代码用于复制一个流到另一个:

byte[] buffer = new byte[bufferSize];
int read;
while ((read = Read(buffer, 0, buffer.Length)) != 0)
    destination.Write(buffer, 0, read);

这让我绝对清楚0代表流的结束而不是那个&#34;现在没有什么可读的&#34;。

任何有关0的返回值具有第二含义的建议都是错误的,因为这会导致CopyTo的实现不正确。

简而言之,要将流读到最后,请继续阅读,直到Read返回0(或抛出异常)。