У меня есть клиентское приложение, которое отправляет файл на сервер. Проблема в том, что в клиентской части файл читается правильно, я могу сохранить байтовый массив снова после того, как прочитал его, и он сохраняется как действительный jpg. Однако на стороне сервера в некоторых местах данные повреждены. Все, что я делаю, это продолжаю добавлять в список все входящие данные, пока клиент не закроет соединение.
Я перекрыл отправленные / полученные данные клиента и сервера, и, как вы можете видеть, есть места, где данные не совпадают: http://s16.postimage.org/mtmm1hssl/corrupted_data.png
Я не понимаю, как это возможно, я использую большой буфер, и изображение довольно маленькое, поэтому даже когда изображение принимается сервером в виде одного «чанка», данные по-прежнему повреждены.
Есть идеи, почему это происходит?
UPDATE:
Сторона клиента:
Я загружаю изображение с помощью 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");
Изображение успешно создано. Поэтому я предполагаю, что клиент отправляет данные правильно.
Сторона SERVER:
Я собираю данные с помощью функции 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)
{
}
}
UPDATE2:
Похоже, что эти строки вызывают проблемы:
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 непосредственно в буфере повлиял на буфер