C# 为什么流不支持seek操作?

C# 为什么流不支持seek操作?,c#,networkstream,C#,Networkstream,我目前正在使用tcp/ip套件。我正在写一个程序,在发送方端加密文件,在接收方端解密。我在用网络流的长度初始化字节数组时遇到了这个异常。这是我的密码: if (client.Connected) { NetworkStream binarystream = client.GetStream(); byte[] receivebytes = new byte[binarystream.Length]; binarystream.Read(receivebytes, 0, r

我目前正在使用tcp/ip套件。我正在写一个程序,在发送方端加密文件,在接收方端解密。我在用网络流的长度初始化字节数组时遇到了这个异常。这是我的密码:

if (client.Connected)
{
    NetworkStream binarystream = client.GetStream();
    byte[] receivebytes = new byte[binarystream.Length];
    binarystream.Read(receivebytes, 0, receivebytes.Length);
    Stream file = File.OpenWrite(saveFileDialog1.FileName);
    file.Write(receivebytes, 0, receivebytes.Length);
    file.Close();
    binarystream.Close();
}
控件的层次结构确保由
client.GetStream()
返回的流在组成binarystream实例之前已经被使用过。我得到的例外情况是在包含以下内容的行上:

byte[] receivebytes = new byte[binarystream.Length];

它表示流不支持seek操作。这意味着什么?

要确定流的长度,您需要能够读取到流的末尾(即,您将
搜索到流的末尾)。由于这是一个网络流,您不能只这样做,因此您会遇到错误。您将需要一直将字节读入缓冲区,直到流结束,然后才知道有效负载的长度。这里有一个建议:

if (client.Connected)
{
    NetworkStream binarystream = client.GetStream();
    Stream file = File.OpenWrite(saveFileDialog1.FileName);

    byte[] buffer = new byte[10000];
    int bytesRead;
    while (binarystream.DataAvailable)
    {
        bytesRead = binarystream.Read(buffer, 0, buffer.Length);
        file.Write(buffer, 0, bytesRead);
    }

    file.Close();
    binarystream.Close();
}

请注意,我还建议为每个流实例化添加
使用
语句,因为这样可以保证即使在读/写时抛出异常,流也会正确关闭。然后,您可以删除对
Close

的显式调用。这是流的正常状态。你需要在思想上对它进行建模,就像春天的一条沙漠小河一样,涓涓细流就像小溪在涓涓细流。你不知道它什么时候会干涸,这就需要一个能准确预测雨什么时候会停的天气预报

这样的天气预报肯定存在。如果它实际上是一个MemoryStream,那么就没有问题了,它可以访问所有字节,这样它就可以可靠地告诉您它何时耗尽。或者文件流,现在操作系统的文件系统可以提供预测。文件数据的目录条目记录文件的长度

对于TCP流来说,这变得困难得多。TCP协议本身根本不提供信息。您只能继续调用套接字的Read()方法,当它返回0时,您就知道它停止了


这通常需要在TCP之上构建一个协议。非常常见的HTTP协议就是一个很好的例子。它确实为您提供了预测。或者你自己做,标准的技术是让发送器先写4个字节,表示接下来有多少数据。但是NetworkStream并不满足特定的协议实现,它模拟了一个通用的网络流。您必须自己添加天气预报。

要确定流的长度,您需要能够读取到流的末尾(即,您
搜索到流的末尾)。由于这是一个网络流,您不能只这样做,因此您会遇到错误。您只需一直将字节读入缓冲区,直到流结束,然后才能知道有效负载的长度。@SimonMᶜKenzie你应该把它作为一个答案发布。天哪,好吧,这意味着我必须先刷新流,然后再设置字节数组中需要的字节长度,然后读取缓冲区中的所有字节,直到流结束并最终得到它的长度?@Jawad,我在我的答案中添加了一个示例。不需要冲洗。@SimonMᶜKenzie啊好吧,非常好,这不仅仅是一个帮助谢谢你,从那时起我一直在寻找一种方法来缓冲networkstream中的字节。你让它变得更简单了。我发现你提供的解释很有帮助:)我想知道每次循环迭代时缓冲区中的字节是否会被替换,因为每次迭代中存储字节的偏移量总是0。