9

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

4

4 回答 4

17

访问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
}

(这些代码片段的基础来自最有效的从流中读取数据的方法

于 2013-10-15T18:16:55.360 回答
3

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

于 2013-10-15T18:06:32.757 回答
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);
        }
    }
}

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

于 2013-10-15T18:11:18.023 回答
0

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

于 2013-10-20T10:15:17.083 回答