读取-填充整个缓冲区的正确方式(否则抛出异常)
本文关键字:方式 抛出异常 填充 缓冲区 读取 | 更新日期: 2023-09-27 18:24:03
NetworkStream.Read方法文档指出,它在两种情况下返回零:
- 如果没有可供读取的数据,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");
}
}
}
它应该填满整个缓冲区,或者抛出异常(如果连接已关闭或丢失)。正确的方法是什么?
采取基于证据的方法来确定事实。。。如果您查看依赖于方法Stream.InternalCopyTo
的Stream.CopyTo
的源代码,您将看到以下用于将一个流复制到另一个流的代码:
byte[] buffer = new byte[bufferSize];
int read;
while ((read = Read(buffer, 0, buffer.Length)) != 0)
destination.Write(buffer, 0, read);
这让我非常清楚,0
代表流的结束,而不是"现在没有什么可读的"。
任何关于0
的返回值具有第二含义的建议都是不正确的,因为这会使CopyTo
的实现不正确。
简而言之,要将流读取到底,请继续读取,直到Read
返回0
(或抛出异常)。