2011-02-15 55 views
2

我有一個具有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的第一個字節和第二個字節之間。

有沒有人有任何想法,這2個字節可能來自哪裏?我檢查了我的代碼,並且每個寫入流的地方都會被跟蹤,所以看起來並不像它們實際寫入流。值得注意的是,在當前的實現中,s1總是0。

+0

那豈不是更容易地創建一個對象,將存儲所有信息,然後序列化/反序列化它?你可能會發現你避免了這些類型的問題。 – 2011-02-15 11:12:28

+0

@Phil我完全同意 - 像我這樣瘋狂的傻瓜花了很多時間編寫非常複雜的序列化代碼,以便大多數人不必這樣做。但有時你不會選擇格式; p – 2011-02-15 11:31:53

回答

2

任何時候你做一個stream.Read(bytes, 0, 4)你沒有檢查結果代碼。總是有足夠的數據填充4個字節是很少見的。將它重構成一個「讀我4字節」的方法,正確地執行它,檢查(循環)4個字節已被讀取。

實際上,我覺得奇怪的是你在填充緩衝區時正確地做了這個,而不是在讀取ints/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)