我有一个将文件发送到服务器的客户端应用程序。问题是在客户端部分正确读取文件,我可以在读取后再次保存字节数组,并将其保存为有效的jpg。但是,在服务器端,数据在某些地方会被破坏。我所做的就是继续向List添加所有传入数据,直到客户端关闭连接。
我重复发送/接收的客户端和服务器数据,您可以看到数据不匹配的地方: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)
{
}
}
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);
如何在不使用Decoder的情况下将数据提取到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会影响缓冲区。
答案 0 :(得分:2)
听起来像编码问题。
这里的关键概念是编码用于文本,而图像不是文本。
在发送之前或接收之后,不要尝试对字节进行编码或解码。
同样,如果您从文件中读取或写入图像,请勿尝试编码或解码,请使用二进制模式。
只是不要尝试将字节转换为字符,没有有意义的方法。