.net 获取NetworkStream中可用数据的长度

xytpbqjk  于 12个月前  发布在  .NET
关注(0)|答案(5)|浏览(162)

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

vtwuwzda

vtwuwzda1#

当访问Stream s时,您通常以小块的形式读取和写入数据(例如,100字节左右),或者使用像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
}

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

lskq00tm

lskq00tm2#

网络流没有固有的长度。您将不得不发送数据的长度以从另一端跟随,或者将所有传入的数据读取到不同的流中,在那里您可以访问长度信息。

ckocjqey

ckocjqey3#

问题是,你还不能确定所有的数据都被套接字读取了,更多的数据随时可能进来。即使你知道需要多少数据,比如说你有一个包含长度的包头,这也是尝试。可能还没有接收到整个分组。
如果你正在阅读任意数据(比如一个文件),你应该有一个合理大小的缓冲区(比如1 k-10 k或者任何你认为最适合你的场景的缓冲区),然后在从流中读取数据时将数据写入文件。

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:)只要确保所有数据都已读取,包括尚未通过网络的数据。

zbq4xfa0

zbq4xfa04#

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

ldioqlga

ldioqlga5#

BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, pars); // pars - some array of standart (not user) types
byte[] buff = BitConverter.GetBytes((Int32)ms.Length);
socket.Send(buff);
socket.Receive(buff);  // read for server answer
if (BitConverter.ToInt32(buff, 0) == 200)
{
    NetworkStream ns = new NetworkStream(socket);
    ms.CopyTo(ns);
}

相关问题