如何从NetworkStream获取所有数据

本文关键字:数据 获取 NetworkStream | 更新日期: 2023-09-27 18:24:33

我正在尝试读取通过TCP/IP连接的机器缓冲区中的所有数据,但我不知道为什么我没有获得所有数据,有些数据正在丢失。这是我正在使用的代码。。

using (NetworkStream stream = client.GetStream())
{
    byte[] data = new byte[1024];
    int numBytesRead = stream.Read(data, 0, data.Length);
    if (numBytesRead > 0)
    {
       string str= Encoding.ASCII.GetString(data, 0, numBytesRead);
    }
}

请告诉我我缺了什么才能从机器上得到所有的数据。提前谢谢。。

如何从NetworkStream获取所有数据

代码的问题是,如果数据大小大于缓冲区大小(在您的情况下为1024字节),您将无法获得所有数据,因此您必须读取循环中的流。然后您可以Write MemoryStream中的所有数据,直到NetworkStream结束。


      string str;
      using (NetworkStream stream = client.GetStream())
      {
            byte[] data = new byte[1024];
            using (MemoryStream ms = new MemoryStream())
            {
                int numBytesRead ;
                while ((numBytesRead = stream.Read(data, 0, data.Length)) > 0)
                {
                    ms.Write(data, 0, numBytesRead);

                }
               str = Encoding.ASCII.GetString(ms.ToArray(), 0, (int)ms.Length);
            }
        }

MSDN中的这个例子:NetworkStream.DataAvailable显示了如何使用该属性来实现这一点:

// Examples for CanRead, Read, and DataAvailable. 
// Check to see if this NetworkStream is readable. 
if(myNetworkStream.CanRead)
{
    byte[] myReadBuffer = new byte[1024];
    StringBuilder myCompleteMessage = new StringBuilder();
    int numberOfBytesRead = 0;
    // Incoming message may be larger than the buffer size. 
    do{
         numberOfBytesRead = myNetworkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
         myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));
    }
    while(myNetworkStream.DataAvailable);
    // Print out the received message to the console.
    Console.WriteLine("You received the following message : " +
                                 myCompleteMessage);
}
else
{
     Console.WriteLine("Sorry.  You cannot read from this NetworkStream.");
}

试试这个:

 private string GetResponse(NetworkStream stream)
    {
        byte[] data = new byte[1024];
        using (MemoryStream memoryStream = new MemoryStream())
        {
            do
            {
                stream.Read(data, 0, data.Length);
                memoryStream.Write(data, 0, data.Length);
            } while (stream.DataAvailable);
            return Encoding.ASCII.GetString(memoryStream.ToArray(), 0, (int)memoryStream.Length);
        }
    }

试试这个代码:

using (NetworkStream stream = client.GetStream())
    {
         while (!stream.DataAvailable)
         {
             Thread.Sleep(20);
         }
        
         if (stream.DataAvailable && stream.CanRead)
         {
              Byte[] data = new Byte[1024];
              List<byte> allData = new List<byte>();
        
              do
              {
                    int numBytesRead = stream.Read(data,0,data.Length);
    
                    if (numBytesRead == data.Length)
                    {
                         allData.AddRange(data);
                    }
                    else if (numBytesRead > 0)
                    {
                         allData.AddRange(data.Take(numBytesRead));
                    }                                    
               } while (stream.DataAvailable);
          }
    }
      

希望这有帮助,它应该可以防止您错过发送给您的任何数据。

同步方法有时不显示请求正文。使用异步方法可以稳定地显示请求体。

string request = default(string);
StringBuilder sb = new StringBuilder();
byte[] buffer = new  byte[client.ReceiveBufferSize];
int bytesCount;
if (client.GetStream().CanRead)
{
    do
    {
        bytesCount = client.GetStream().ReadAsync(buffer, 0, buffer.Length).Result;
        sb.Append(Encoding.UTF8.GetString(buffer, 0, bytesCount));
    }
    while(client.GetStream().DataAvailable);
    request = sb.ToString();
}

TCP本身并没有任何方法来定义"数据结束"条件。这是应用程序级portocol的责任。

例如,请参阅HTTP请求描述:

客户端请求(在这种情况下由请求行和只有一个标题字段组成)后面跟着一个空行,因此请求以双换行结束

因此,对于请求,数据的末尾由两个换行序列决定。回应:

Content Type指定HTTP消息传输的数据的Internet媒体类型,而Content Length表示其长度(以字节为单位)。

响应内容大小在数据之前的标头中指定。因此,如何对一次传输的数据量进行编码取决于您——它可以是数据开始时的前2或4个字节,可以是要读取的总大小,也可以是更复杂的方式(如果需要)。

对于我的场景,消息本身告诉了后续消息的长度。这是代码

 int lengthOfMessage=1024;
 string message = "";
 using (MemoryStream ms = new MemoryStream())
 {
      int numBytesRead;
      while ((numBytesRead = memStream.Read(MessageBytes, 0, lengthOfMessage)) > 0)
      {
            lengthOfMessage = lengthOfMessage - numBytesRead;
            ms.Write(MessageBytes, 0, numBytesRead);
      }
      message = Encoding.ASCII.GetString(ms.ToArray(), 0, (int)ms.Length);
 }

@George Chondrompilas答案是正确的,但您可以使用CopyTo函数,而不是自己编写:

https://stackoverflow.com/a/65188160/4120180