通过 TCP 接收数据:MemoryStream 包含比预期更多的数据
Receiving data via TCP: MemoryStream contains more data than expected
我托管了一个服务器,该服务器从远程 TCP 客户端(我也控制)接收数据。这是处理传入数据的方法:
private static async Task ReceiveDataFromRemoteSocket(
Socket socket,
int numBytesExpectedToReceive)
{
int numBytesLeftToReceive = numBytesExpectedToReceive;
using (MemoryStream memoryStream = new MemoryStream(numBytesExpectedToReceive))
{
byte[] dataBuffer = new byte[1024];
ArraySegment<byte> dataBufferSegment = new ArraySegment<byte>(dataBuffer);
int totalBytesReceived = 0;
while (numBytesLeftToReceive > 0)
{
Array.Clear(dataBuffer, 0, dataBuffer.Length);
int numBytesReceived = await socket.ReceiveAsync(dataBufferSegment, SocketFlags.Partial);
Console.WriteLine($"Received {numBytesReceived} bytes of data at {DateTime.UtcNow.ToShortTimeString()}.");
totalBytesReceived += numBytesReceived;
memoryStream.Write(
dataBuffer,
0,
numBytesLeftToReceive < dataBuffer.Length ? numBytesLeftToReceive : dataBuffer.Length);
numBytesLeftToReceive -= numBytesReceived;
}
Console.WriteLine($"Total number of bytes received, according to tally: {totalBytesReceived}.");
Console.WriteLine($"Memory stream: Contains {memoryStream.Length} bytes' worth of data.");
}
}
numBytesExpectedToReceive
是从 header.
检索到的信息
这是我控制台上的输出:
Accepted connection request from XX.XX.XXX.XXX:56767 at 4/30/2019
10:39:11 AM.
Expecting to receive 41898 bytes' worth of data from
XX.XX.XXX.XXX:56767.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes
of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes
of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 416 bytes of data at 10:39 AM.
Received 1024 bytes of
data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes
of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes
of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes
of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes
of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes
of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes
of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 96 bytes of
data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes
of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes
of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes
of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes
of data at 10:39 AM.
Received 512 bytes of data at 10:39 AM.
Total number of bytes received, according to tally:
41984.
Memory stream: Contains 43434 bytes' worth of data.
如您所见,内存流包含 43434 字节的数据,尽管我预计它只包含 41984 字节。
这会导致很多问题,例如如果我通过编写 new ZipArchive(memoryStream);
创建 ZipArchive
的新实例,我最终会得到一个 InvalidDataException
,即使我知道我的远程 TCP 客户端发送了一个有效的 zip 文件。
- 为什么内存流包含的字节数比通过 TCP 实际接收到的字节数多?
- 如何删除这些 "junk data"(因为没有更好的术语),以便我可以成功地重建发送给我的数据,例如通过将内存流传递给
ZipArchive
构造函数?
问题出在你写数据的地方:
memoryStream.Write(
dataBuffer,
0,
numBytesLeftToReceive < dataBuffer.Length ? numBytesLeftToReceive : dataBuffer.Length);
你完全忽略了你收到的数量,而是检查是否有比自助餐大小更多的数据要接收,如果有你写整个缓冲区。
您可以在输出中看到有时您没有收到完整的缓冲区。然而你仍然写了整个缓冲区。
始终根据您收到的金额来写。不要根据数据的长度做任何奇怪的比较:
memoryStream.Write(
dataBuffer,
0,
numBytesReceived);
我托管了一个服务器,该服务器从远程 TCP 客户端(我也控制)接收数据。这是处理传入数据的方法:
private static async Task ReceiveDataFromRemoteSocket(
Socket socket,
int numBytesExpectedToReceive)
{
int numBytesLeftToReceive = numBytesExpectedToReceive;
using (MemoryStream memoryStream = new MemoryStream(numBytesExpectedToReceive))
{
byte[] dataBuffer = new byte[1024];
ArraySegment<byte> dataBufferSegment = new ArraySegment<byte>(dataBuffer);
int totalBytesReceived = 0;
while (numBytesLeftToReceive > 0)
{
Array.Clear(dataBuffer, 0, dataBuffer.Length);
int numBytesReceived = await socket.ReceiveAsync(dataBufferSegment, SocketFlags.Partial);
Console.WriteLine($"Received {numBytesReceived} bytes of data at {DateTime.UtcNow.ToShortTimeString()}.");
totalBytesReceived += numBytesReceived;
memoryStream.Write(
dataBuffer,
0,
numBytesLeftToReceive < dataBuffer.Length ? numBytesLeftToReceive : dataBuffer.Length);
numBytesLeftToReceive -= numBytesReceived;
}
Console.WriteLine($"Total number of bytes received, according to tally: {totalBytesReceived}.");
Console.WriteLine($"Memory stream: Contains {memoryStream.Length} bytes' worth of data.");
}
}
numBytesExpectedToReceive
是从 header.
这是我控制台上的输出:
Accepted connection request from XX.XX.XXX.XXX:56767 at 4/30/2019 10:39:11 AM.
Expecting to receive 41898 bytes' worth of data from XX.XX.XXX.XXX:56767.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 416 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 96 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 1024 bytes of data at 10:39 AM.
Received 512 bytes of data at 10:39 AM.
Total number of bytes received, according to tally: 41984.
Memory stream: Contains 43434 bytes' worth of data.
如您所见,内存流包含 43434 字节的数据,尽管我预计它只包含 41984 字节。
这会导致很多问题,例如如果我通过编写 new ZipArchive(memoryStream);
创建 ZipArchive
的新实例,我最终会得到一个 InvalidDataException
,即使我知道我的远程 TCP 客户端发送了一个有效的 zip 文件。
- 为什么内存流包含的字节数比通过 TCP 实际接收到的字节数多?
- 如何删除这些 "junk data"(因为没有更好的术语),以便我可以成功地重建发送给我的数据,例如通过将内存流传递给
ZipArchive
构造函数?
问题出在你写数据的地方:
memoryStream.Write(
dataBuffer,
0,
numBytesLeftToReceive < dataBuffer.Length ? numBytesLeftToReceive : dataBuffer.Length);
你完全忽略了你收到的数量,而是检查是否有比自助餐大小更多的数据要接收,如果有你写整个缓冲区。
您可以在输出中看到有时您没有收到完整的缓冲区。然而你仍然写了整个缓冲区。
始终根据您收到的金额来写。不要根据数据的长度做任何奇怪的比较:
memoryStream.Write(
dataBuffer,
0,
numBytesReceived);