TCP客户端-数据只在某些部分损坏

本文关键字:些部 损坏 客户端 数据 TCP | 更新日期: 2023-09-27 18:26:32

我有一个客户端应用程序,它将文件发送到服务器。问题是,在客户端部分,文件读取正确,我可以在读取后再次保存字节数组,并将其保存为有效的jpg。然而,在服务器端,数据在某些地方会被破坏。我所做的就是不断地将所有传入的数据添加到列表中,直到客户端关闭连接。

我重叠了发送/接收的客户端和服务器数据,正如您所看到的,有些地方的数据不匹配:http://s16.postimage.org/mtmm1hssl/corrupted_data.png

我不明白这怎么可能,我使用了一个大缓冲区,而图像相当小,所以即使服务器在一个"区块"中接收到图像,数据仍然损坏。

你知道为什么会这样吗?

更新:

客户端:

我正在使用HttpWebRequest:获取图像

                  List<byte> test_buffer = new List<byte>();
                  using (Stream MyResponseStream = hwresponse.GetResponseStream())
                  {
                      byte[] MyBuffer = new byte[4096];
                      int BytesRead;
                      while (0 < (BytesRead = MyResponseStream.Read(MyBuffer, 0, MyBuffer.Length)))
                      {
                          for (int i = 0; i < BytesRead; i++)
                          {
                              test_buffer.Add(MyBuffer[i]); // just for testing
                          }
                          TCP_R.SendBytes(MyBuffer); // send data back to server
                      }
                  }
                  TCP_R.Close(); // tell server that we're done sending data

TCP_R是一个处理所有TCP内容(连接到服务器/发送数据)的类

这是TCP_R.SendBytes函数:

    public void SendBytes(Byte[] data)
    {
        try
        {
            if (m_clientSocket != null)
            {
                m_clientSocket.Send(data);
            }
        }
        catch (SocketException se)
        {
            log("send_bytes err: " + se.Message);
        }
    }

请注意,我使用test_buffer来收集所有字节,以验证是否所有内容都被正确接收。如果我使用这个代码:

                  MemoryStream ms = new MemoryStream(test_buffer.ToArray());
                  Image returnImage = Image.FromStream(ms);
                  returnImage.Save("image.jpg");

图像创建成功。所以我认为客户端发送数据是正确的。

服务器端:

我使用OnDataReceived函数收集数据,并在REQUEST_RESPONSE中构建所有数据,即List<byte>:

  public void OnDataReceived(IAsyncResult asyn)
    {
        try
        {
            SocketPacket socketData = (SocketPacket)asyn.AsyncState; // cast
            int iRx = 0;
                iRx = socketData.m_currentSocket.EndReceive(asyn);
                char[] chars = new char[iRx + 1];
                System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder(); // CAN THIS BE CAUSING THE PROBLEM!?!
                int charLen = d.GetChars(socketData.dataBuffer, 0, iRx, chars, 0);

                for (int s = 0; s < charLen; s++)
                {
                    RESPONSE_DATA.Add(socketData.dataBuffer[s]); // Collect response data
                }
                WaitForData(socketData.m_currentSocket, socketData.socket_id, REQUEST_INDEX_ID);
            }
        }
        catch (ObjectDisposedException)
        {
        }
        catch (SocketException se)
        {
        }
    }

更新2:看来是这些线路造成了问题:

                System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder(); // CAN THIS BE CAUSING THE PROBLEM!?!
                int charLen = d.GetChars(socketData.dataBuffer, 0, iRx, chars, 0);

如何在不使用解码器的情况下将数据提取到socketData.dataBuffer中?

解决方案:即使我直接从dataBuffer读取,"d.GetChars(socketData.dataBuffer.."行不知怎么搞砸了缓冲区,因此我得到了搞砸的数据。我仍然需要使用GetChars将数据包的第一部分读取为字符串,所以我只需更改:

 int charLen = d.GetChars(socketData.dataBuffer, 0, iRx, chars, 0);

至:

 byte[] tmp_a = new byte[socketData.dataBuffer.Length];
 tmp_a = socketData.dataBuffer;
 int charLen = d.GetChars(tmp_a, 0, iRx, chars, 0);

现在一切都很顺利。显然,在缓冲区上直接调用getChars会影响缓冲区。

TCP客户端-数据只在某些部分损坏

听起来像是一个编码问题。

这里的关键概念是编码是针对文本的,而图像不是文本。

在发送之前或接收之后,不要尝试对字节进行编码或解码。

同样,如果您从文件中读取或向文件中写入图像,请不要尝试编码或解码,而是使用二进制模式。

只是不要试图将字节转换为字符,没有任何有意义的方法。