TCP-клиент - данные повреждены только в некоторых частях

У меня есть клиентское приложение, которое отправляет файл на сервер. Проблема в том, что в клиентской части файл читается правильно, я могу снова сохранить байтовый массив после того, как прочитал его, и он сохранился как действительный 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 непосредственно в буфере повлиял на буфер.

1 ответ

Похоже, проблема кодирования.

Ключевой концепцией здесь является то, что кодировка предназначена для текста, а изображения не являются текстом.

Не пытайтесь кодировать или декодировать байты перед отправкой или после получения.

Точно так же, если вы читаете или записываете изображение из или в файл, не пытайтесь кодировать или декодировать, используйте двоичный режим.

Только не пытайтесь конвертировать байты в символы, нет никакого осмысленного способа сделать это.

Другие вопросы по тегам