为什么 BufferedStream.Write 会抛出 "This stream does not support seek operations" 错误?

10

这个问题困扰着我。我在没有调用它的情况下收到有关“seek”的错误?

我的代码看起来像这样:

// send 42
uint value = 42;
byte[] msg = BitConverter.GetBytes(value);
stream.Write(msg, 0, sizeof(uint));

但我得到了这个异常:

System.NotSupportedException was unhandled
Message="This stream does not support seek operations."
Source="System"
StackTrace:
   at System.Net.Sockets.NetworkStream.Seek(Int64 offset, SeekOrigin origin)
   at System.IO.BufferedStream.FlushRead()
   at System.IO.BufferedStream.Write(Byte[] array, Int32 offset, Int32 count)
...

流的类型是System.IO.BufferedStream。可能出了什么问题?

编辑,附加更多信息:

sizeof(uint)==msg.length在这种情况下成立。
该流声明为stream = new BufferedStream(new NetworkStream(socket), 1024)

编辑:

找到了!虽然可以在单个NetworkStream上读写,但是当切换到BufferedStream时,需要分别为读取和写入创建一个单独的流。显然,可以在同一套接字上两次调用NetworkStream构造函数来实现。

如果可以的话,我将接受Justin和Hans的答案,因为一个让我完全理解了问题出在哪里,而另一个则引导我找到了解决方案。感谢大家!


如果有帮助的话,BufferedStream在NetworkStream之上。 - redtuna
你是如何声明缓冲流的?它的大小是多少?它关联的流类型是什么?另外,sizeof(uint)不应该改为msg.length吗? - Mark Schultheiss
2个回答

10
问题出在BufferedStream的内部实现上(以及可能在尝试写入之前已经使用了BufferedStream进行读取)。当您尝试向BufferedStream写入时,会按照以下顺序检查(所有代码均从Reflector中提取自框架):首先确定我们是否在写缓冲区的开头。
if(this._writePos == 0)

我们可以写入底层流吗?

if(!this._s.CanWrite) // throw error

读缓冲区是否为空?

if(this._readPos < this._readLen)
{
    // FlushRead() will attempt to call Seek()
    this.FlushRead();
}
如果读取缓冲区中有未读数据,则在写入之前会尝试刷新缓冲区。FlushRead() 调用了 Seek(),这就是导致你的错误发生的原因。

好的,所以当存在未读数据时,我无法调用write...这基本上意味着我不能在同一个BufferedStream上有一个线程读取和另一个线程写入。现在,考虑到我连接到另一台计算机时有一个NetworkStream,我该如何从中获取两个BufferedStreams? - redtuna
@redtuna - 如果这是你的目标,你需要创建两个NetworkStreams来匹配两个BufferedStreams。否则,你将会遇到许多与共享NetworkStream相关的问题。 - Justin Niessner

5

你一定是之前从那个BufferedStream中读取的。它正在从NetworkStream中获取字节流。这些流是单向的,你只能从中读取或只能写入,这取决于创建它们的方式。如果需要更多帮助,请发布创建NetworkStream的代码。


你可能有所发现:另一个线程可能正在尝试同时读取,这可能是问题的原因。文档确实说可以从同一个 BufferedStream 中读取和写入(在我的情况下,.CanRead 和 .CanWrite 都为 true),但也许不能同时进行。 - redtuna
如果我理解正确的话,你应该有两个NetworkStreams和两个BufferedStreams。从其中一个读取并写入另一个。 - Platinum Azure
@red:是的,BufferedStream支持读写。但它所读/写的流可能不支持它。NetworkStream则不支持。 - Hans Passant
@red:打开用于写入的 NetworkStream 不会有未读数据。我首先会检查您是否正在使用正确的 NS。请关注网络流,而不是 BufferedStream。 - Hans Passant
好的,汉斯,让我重新表达一下。我有一个已连接的套接字。我可以多次调用 new NetworkStream(socket) 吗? - redtuna
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接