如何从NetworkStream获取所有数据

时间:2014-09-26 11:34:00

标签: c# tcp tcpclient tcp-ip networkstream

我正在尝试读取通过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);
    }
}

请告诉我从机器上获取所有数据所缺少的内容。 提前谢谢..

9 个答案:

答案 0 :(得分:21)

代码的问题在于,如果数据大小大于缓冲区大小(在您的情况下为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);
            }
        }

答案 1 :(得分:5)

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.");
}

答案 2 :(得分:2)

试试这段代码:

using (NetworkStream stream = client.GetStream())
    {
         do
         {
           Thread.Sleep(20);
         } while (!stream.DataAvailable);

         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(bytes));
                    }                                    
               } while (stream.DataAvailable);
          }
    }

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

答案 3 :(得分:1)

试试这个:

 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);
        }
    }

答案 4 :(得分:0)

TCP本身没有任何方法来定义&#34;数据结束&#34;条件。这是应用程序级别协议的责任。

例如,请参阅HTTP请求说明:

  

客户端请求(包含请求行的这种情况,只有一个标题字段)后跟一个空行,以便请求以双换行符结束

因此,对于请求,数据结束由两个换行序列决定。并回应:

  

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

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

答案 5 :(得分:0)

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

 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);
 }

答案 6 :(得分:0)

加入这个问题有点晚了,但是我只是想问自己,什么是最整洁的方法。当协议未知时。 这是我的结论

先前答案中提到的while循环无法在NetworkStream上正常工作,它们会失败,并且您根本不会获得任何数据。

我还没有尝试过DataAvailable,也不知道它如何工作,所以我更喜欢任何人都可以理解的版本。

var ms = new MemoryStream();
byte[] data = new byte[1024];
int numBytesRead;

do
{
    numBytesRead = stream.Read(data, 0, data.Length);
    ms.Write(data, 0, numBytesRead);

} while (numBytesRead == data.Length);

var str = Encoding.ASCII.GetString(ms.ToArray());

答案 7 :(得分:0)

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

<script src="https://animejs.com/lib/anime.min.js"></script>

<div class="b-main">
  <div class="b1"></div>
  <div class="b2"></div>
  <div class="b3"></div>
  <div class="b4"></div>
</div>

答案 8 :(得分:0)

@George Chondrompilas答案是正确的,但是您可以使用CopyTo函数来完成此操作,而不必自己编写它:

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