我希望能够从 C# 中的 TCP 网络流中获取可用数据的长度,以在从网络流中读取之前设置缓冲区的大小。有一个NetworkStream.Length
属性,但还没有实现,我不想为缓冲区分配一个巨大的大小,因为它会占用太多空间。我认为这样做的唯一方法是在数据传输之前用另一个告诉大小,但这似乎有点混乱。什么是我做这件事的最佳方式。
4 回答
访问Stream
s时,您通常以小块(例如千字节左右)读取和写入数据,或者使用类似的方法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
}
(这些代码片段的基础来自最有效的从流中读取数据的方法)
网络流没有固有的长度。您要么必须从另一端发送要跟随的数据长度,要么将所有传入数据读取到不同的流中,您可以在其中访问长度信息。
问题是,您还不能确定套接字是否读取了所有数据,更多数据可能随时进入。即使您以某种方式确实知道需要多少数据,例如您是否有一个包含长度的包头,也可以尝试这样做。可能还没有收到整个数据包。
如果您正在读取任意数据(可能像文件),您应该有一个合理大小的缓冲区(例如 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 建议的那样使用 :) 只需确保所有数据确实已被读取,包括尚未通过网络传输的数据。
您可以先发送传入数据的长度。例如:你有data = byte[16]
你要发送。因此,首先您发送 16 并在服务器上定义,该长度始终为 2(因为 16 有两个字符)。现在你知道incomingLength = 16
. 您现在可以等待长度的数据incomingLength
。