TcpListener随机截断字节数组

时间:2012-03-13 15:00:06

标签: c# .net networking

我正在编写一个基本上是用于存储图像的图像备份服务器。它是一种单向服务,不会向客户端返回除基本成功或失败消息之外的任何内容。

我遇到的问题是,当我通过网络流发送字节数组时,它会在流的末尾随机位置被切断。当我在开发计算机上运行服务器并在本地连接时,我没有这个问题,而只是在服务器部署在远程服务器上时才会出现这种情况。

当我发送非常小的数组(<512字节)时,服务器成功接收整个流,但是在大于2000字节的流上,我遇到了问题。客户端的代码如下:

    try
    {
        TcpClient Voice = new System.Net.Sockets.TcpClient();
        //Obviously I use the remote IP when it is deployed - but have altered it for privacy.
        IPEndPoint BackupServer = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 57000);

        Voice.Connect(BackupServer);
        NetworkStream DataStream = Voice.GetStream();

        byte[] buffer = new ASCIIEncoding().GetBytes(ImageData.GetXml());
        DataStream.Write(buffer, 0, buffer.Length);
        DataStream.Flush();
      }
      catch 
      {
      }
      try
      {
        buffer = new byte[4096];
        int read = DataStream.Read(buffer, 0, buffer.Length);
        MessageBox.Show(new ASCIIEncoding().GetString(buffer) + " : " + read.ToString());
      }
      catch
      {

      }

无论我发送的数据大小如何,客户端代码都会执行而不会出现任何错误或问题。

服务器端的代码如下:

  private void BackMeUp(object voice)
  {
    TcpClient Voice = (TcpClient)voice;
    Voice.ReceiveTimeout = 30000;
    NetworkStream DataStream = Voice.GetStream();
    try
    {            
      bool ShouldLoop = true;
      //int loops = 0;
      int loops = -1;
      byte[] input = new byte[2048];
      byte[] buffer = new byte[0];

      //while (ShouldLoop)
      while(loops != 0)
      {
        loops = DataStream.Read(input, 0, 2048);

        for (int x = 0; x < loops; x++)
        {                        
          Array.Resize(ref buffer, buffer.Length + 1);
          buffer[buffer.Length - 1] = input[x];                       
        }
        //if (loops < 2048)
        //{
          //ShouldLoop = false;
          //break;
        //}                    
      }

      while (true)
      {   
        StringReader Reader = new StringReader(new ASCIIEncoding().GetString(buffer, 0, buffer.Length));
        DataSet DS = new DataSet();
        DS.ReadXml(Reader);

        if (DS.Tables.Count > 0)
        {
          if (DS.Tables["Images"].Rows.Count > 0)
          {
            foreach (DataRow row in DS.Tables["Images"].Rows)
            {
                  //
            }
          }
        }

        string response = "Got it!";                    

        DataStream.Write(new ASCIIEncoding().GetBytes(response), 0, response.Length);
        DataStream.Flush();

        Voice.Close();
        break;                  
      }
    }
    catch (Exception Ex)
    {
      File.WriteAllText("Elog.txt", Ex.Message + " " + (Ex.InnerException != null ? Ex.InnerException.ToString() : " no Inner"));
      Voice.Close();
    }
  }

服务器接收数据正常,并在流到达结束时关闭流,但数据被截断,当我尝试重建数据集时出现错误。

我的印象是这与发送流所需的时间有关,而且我已经使用了Close和Flush命令,但我觉得我只是在黑暗中拍摄。任何帮助将不胜感激。

问题的简明版本:TcpListener涉及哪些因素可能导致a)截断流。或b)在读取所有字节之前过早关闭流。当有问题的监听器位于远程主机而不是本地服务器上时。

1 个答案:

答案 0 :(得分:3)

Read方法不必一次返回您请求的字节数或整个流。特别是如果流很慢,它将以小块返回。

重复调用Read方法,并处理您获得的每个块的数据。当流被读取到结尾时,Read方法返回零:

buffer = new byte[4096];
do {
  int read = DataStream.Read(buffer, 0, buffer.Length);
  if (read != 0) {
    // handle the first "read" bytes of the buffer (index 0 to read-1)
  }
} while (read != 0);

如果您知道您的缓冲区对于任何流都足够了,您可以填充缓冲区并在之后处理它:

buffer = new byte[4096];
int offset = 0;
do {
  int read = DataStream.Read(buffer, offset, buffer.Length - offset);
  offset += read;
} while (read != 0);
// handle the first "offset" bytes of the buffer (index 0 to offset-1)