我已经编写了一些代码,用于在发送之前使用已知大小的NetworkStream发送byte []数组,但是发送的数据和收到的数据在某些位置是差异。
maxsize是我要发送的数据的已知大小。
public static void SendBytes(TcpClient clientSocket, byte[] outStream)
{
Debug.WriteLine("SendBytes() number of bytes: " + outStream.Length.ToString());
NetworkStream serverStream = clientSocket.GetStream();
serverStream.Write(outStream, 0, outStream.Length);
//serverStream.Flush();
}
public static byte[] ReceiveBytes(TcpClient clientSocket, int MAX_SIZE)
{
Debug.WriteLine("[" + DateTime.Now.ToString("G") + "] - " + "ReceiveBytes() started.");
NetworkStream networkStream = clientSocket.GetStream();
byte[] bytesFrom = new byte[MAX_SIZE];
clientSocket.ReceiveBufferSize = MAX_SIZE;
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
Debug.WriteLine("[" + DateTime.Now.ToString("G") + "] - " + "ReceiveBytes(), received number of raw bytes: " + bytesFrom.Length.ToString());
return CommonUtils.SubArray(bytesFrom, 0, MAX_SIZE);
}
如果发送数据(十六进制中的字节(:A7 FC D0 51 0E 99 CF 0D 00,收到的数据是:A7 FC D0 51 0E 99 CF 0d 53
很可能是由于数据包结构而看到的垃圾;TCP仅保证正确的字节将以正确的顺序(或流故障(到达 - 它对它们到达的块没有说明。因此,您是 cavital 您:
- 从
Read
捕获返回值,只有从任何块中的许多字节 - 执行您自己的框架 - 即独立于零件到达的方式将流批准为消息
如果您的消息始终是固定大小,则" 2"将变为"缓冲区数据,直到我至少具有n个字节为止,然后在n块中处理数据,保留剩下的所有内容,然后恢复缓冲"。但是在一般情况下,它可能是"缓冲区,直到我看到哨兵值,例如线馈线",或"缓冲区",直到我拥有完整的标头,然后解析标头以查看要期望的数据,然后才直到我有很多数据"。
有一些工具和实用程序可以帮助使框架和处理积压更简单 - 例如,使用新的"管道" API,这只是检查管道并告诉管道要消耗多少的情况(而不是为您提供一切,而您目前无法拒绝数据( - 但是,从Stream
转换为"管道"对大多数人来说是很多更改。
在您的情况下,您可能可以使用:
byte[] bytesFrom = new byte[MAX_SIZE];
int outstanding = MAX_SIZE, read, offset = 0;
while (outstanding > 0 && (read = networkStream.Read(bytesFrom, offset, outstanding)) > 0)
{
offset += read;
outstanding -= read;
}
if (outstanding != 0) throw new EndOfStreamException();
这会创建一个读取循环,该循环完全填充bytesFrom
,或者在例外失败。
Stream.Read
返回一个值,该值指示实际 read。它绝不保证与您要求的金额相同。在您的危险中忽略这个值。
如果您很乐意为整个流分配内存,为什么不将其复制到MemoryStream
中并从中钓鱼完全缓冲呢? Stream.CopyTo
和 Stream.CopyToAsync
是一个不错的高级抽象,使它变得容易。