我已经编写了一些代码,用于在发送之前使用大小为KNOWN的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
答案 0 :(得分:2)
由于数据包的结构化,很可能您会看到垃圾; TCP仅保证正确的字节将以正确的顺序到达(否则将导致流失败)-它没有提及到达它们的块。因此,您重要:
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
,否则会因异常而失败。
答案 1 :(得分:1)
read -p 'Email:' USERMAIL
返回一个值,该值指示 实际上 读取了多少数据。绝不保证与您要求的金额相同。忽略此值,后果自负。
如果您愿意为整个流分配内存,为什么不只复制到Stream.Read
中并从中获取全部缓冲区呢? MemoryStream
和Stream.CopyTo
是很好的高级抽象,可以简化此工作。