获取NetworkStream中可用的数据长度

时间:2013-10-15 18:02:01

标签: c# .net sockets tcp networkstream

我希望能够从C#中的TCP网络流中获取可用数据的长度,以便在从网络流中读取之前设置缓冲区的大小。有一个NetworkStream.Length属性但它尚未实现,我不想为缓冲区分配一个巨大的大小,因为它会占用太多空间。我做这件事的唯一方法是在数据传输之前与另一个告诉大小,但这似乎有点混乱。这对我来说最好的方法是什么。

4 个答案:

答案 0 :(得分:10)

访问Streams时,您通常以小块(例如千字节左右)读取和写入数据,或者使用像CopyTo这样的方法为您执行此操作。

这是一个使用CopyTo将流的内容复制到另一个流并使用自动调整大小的缓冲区从方法返回为byte[]的示例。

using (MemoryStream ms = new MemoryStream())
{
    networkStream.CopyTo(ms);
    return ms.ToArray();
}

这是以相同方式读取数据的代码,但手动更多,这可能更适合您使用,具体取决于您对数据执行的操作:

byte[] buffer = new byte[2048]; // read in chunks of 2KB
int bytesRead;
while((bytesRead = networkStream.Read(buffer, 0, buffer.Length)) > 0)
{
    //do something with data in buffer, up to the size indicated by bytesRead
}

(这些代码段的基础来自Most efficient way of reading data from a stream

答案 1 :(得分:2)

问题是,您无法确定套接字是否已读取所有数据,可能随时会有更多数据进入。即使您以某种方式知道要预期多少数据,也可以尝试,例如,如果您有一个包含长度的包头。可能还没有收到整个数据包。

如果您正在读取任意数据(可能是文件),您应该拥有一个合理大小的缓冲区(例如1k-10k或您认为最适合您的方案的任何内容),然后将数据写入文件中从溪流中读取。

var buffer = byte[1000];
var readBytes = 0;
using(var netstream = GetTheStreamSomhow()){
    using(var fileStream = (GetFileStreamSomeHow())){
        while(netstream.Socket.Connected) //determine if there is more data, here we read until the socket is closed
        {
            readBytes = netstream.Read(buffer,0,buffer.Length);
            fileStrem.Write(buffer,0,buffer.Length);
        }
    }
}

或者只是像Tim建议的那样使用CopyTo :)确保确实已经读取了所有数据,包括尚未通过网络传输的数据。

答案 2 :(得分:1)

网络流没有固有的长度。您将要么必须从另一端发送要跟踪的数据长度,要么将所有传入的数据读入不同的流,您可以在其中访问长度信息。

答案 3 :(得分:0)

您可以先发送传入数据的长度。 例如: 您要发送data = byte[16]。所以首先你发送16并在服务器上定义,这个长度总是2(因为16有两个字符)。现在你知道了incomingLength = 16。您现在可以等待长度为incomingLength的数据。