我有一个带有2个进程的.net应用程序,使用网络流进行通信。 该协议由一组命令组成,一些命令带有参数,这些命令通过流发送到服务器。服务器处理命令,并发送响应。
其中一个命令的协议如下所示:
Dim bytes() As Byte
stream.WriteByte(CmdId)
bytes = BitConverter.GetBytes(bufferSize)
stream.Write(bytes, 0, bytes.Length)
stream.Write(buffer, offset, bufferSize)
bytes = BitConverter.GetBytes(singleValue1)
stream.Write(bytes, 0, bytes.Length)
bytes = BitConverter.GetBytes(singleValue2)
stream.Write(bytes, 0, bytes.Length)
bytes = BitConverter.GetBytes(intValue1)
stream.Write(bytes, 0, bytes.Length)
bytes = BitConverter.GetBytes(intValue2)
stream.Write(bytes, 0, bytes.Length)
所以基本上我发送了一大块字节(长度不一,但是数以千计),其次是2个单词,2个整数)。 在接收端,我有:
Dim bytes(3) As Byte
cmd = stream.readByte()
stream.Read(bytes, 0, 4)
Dim bufferSize As Integer = BitConverter.ToInt32(bytes, 0)
Dim buf(bufferSize - 1) As Byte
Dim nRead As Integer = 0
While nRead < bufferSize
nRead += stream.Read(buf, nRead, bufferSize - nRead)
End While
stream.Read(bytes, 0, 4)
Dim s1 As Single = BitConverter.ToSingle(bytes, 0)
stream.Read(bytes, 0, 4)
Dim s2 As Single = BitConverter.ToSingle(bytes, 0)
stream.Read(bytes, 0, 4)
Dim i1 As Integer = BitConverter.ToInt32(bytes, 0)
stream.Read(bytes, 0, 4)
Dim i2 As Integer = BitConverter.ToInt32(bytes, 0)
通常,这很好用。很少(可能每几百万次调用一次),阅读方得到错误的值。我添加了代码来跟踪发送和接收的值。这表明有时候,读取端会获得两个额外的字节,值为0,这是写入端未发送的。这些额外的字节出现在不同的地方,例如在一个案例中,他们介于i1和i2之间;在另一个中,它们位于s2的第一个和第二个字节之间。
有谁知道这两个字节可能来自哪里?我检查了我的代码,并且跟踪了写入流的每个地方,因此看起来它们实际上并没有写入流。值得注意的是,在当前的实现中,s1始终为0。
答案 0 :(得分:2)
每次执行stream.Read(bytes, 0, 4)
时,都无法检查结果代码。总是有足够的数据来填充4个字节是很少见的。将其重构为“read me 4 bytes”方法,正确执行,检查(循环)已读取的4个字节。
实际上,我发现在填充缓冲区时,正确这一点很奇怪,但在读取int / single时却没有。例如,你可以(用C#术语)
static void Read(Stream stream, byte[] buffer, int offset, int count) {
int read;
while(count > 0 && (read = stream.Read(buffer, offset, count)) > 0) {
count -= read;
offset += read;
}
if(count > 0) throw new EndOfStreamException();
}
然后
Read(stream, bytes, 0, 4)
Dim s1 As Single = BitConverter.ToSingle(bytes, 0)
等