【问题标题】:C# - NetworkStream.Read - correct way to fill the entire buffer (or throw exceptions otherwise)C# - NetworkStream.Read - 填充整个缓冲区的正确方法(否则抛出异常)
【发布时间】:2016-02-27 01:32:16
【问题描述】:

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

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

还有以下观察:

通过调用 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");
        }
    }
}

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

【问题讨论】:

  • 在我看来,MS 不太可能偏离他们的标准做法,即仅在到达流末尾的情况下返回“读取的零字节”。你能具体指出“现在没有什么可读的”时返回零的文件吗?根据我对System.IO.Stream 的所有经验,我认为这是不正确的(如果不是,我有很多修复工作要做)。
  • 所以NetworkStream 派生自抽象Stream 类。这里的文档很清楚:返回:“读入缓冲区的总字节数。如果当前没有那么多字节可用,这可能小于请求的字节数,如果流的末尾有达到了。”我认为任何关于 0 表示“流结束”以外的任何内容的建议都是错误的文档。
  • 链接文档显示“如果没有数据可供读取,Read 方法返回 0”(请参阅​​帖子中的链接,我正在更新我的问题)

标签: c# .net network-programming


【解决方案1】:

采用基于证据的方法来确定事实...如果您查看依赖于方法 Stream.InternalCopyToStream.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(或抛出异常)。

【讨论】:

  • 我更新了我的问题,引用了文档。可能是我理解错了?
  • @Eric.Void 我认为文档令人困惑。我坚持我的回答......返回0 的唯一情况是在流的末尾。 CopyTo 的代码清楚地说明了这一点。对于CanRead,这用于指示调用Read 是否合法(即它是一个可读流)。它与数据是否可用无关,尽管对于所有类型的流,一旦释放流,它将被设置为false
  • @Eric.Void 在未到达流末尾的情况下,Read 将阻塞,直到它可以进行读取并返回非零值。我有 很多 依赖于此的代码。多年来一直完美无缺。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-04
  • 2015-04-29
  • 2018-02-07
  • 1970-01-01
相关资源
最近更新 更多