2015-01-14 66 views
0

通過List<byte[]>()以下代碼迭代然而問題是,由於某些原因,有時lengthBuffer是byteData的不同的大小。GetBytes會比數據返回不同大小實際上字節是

您可以在我打印BitConverter.ToInt32()長度,然後實際byteDataList[i].Length,這兩個數字應該是完全一樣的,有很多他們的時間DebugPrintInGame方法看,但原因不明給我很多的現在他們都沒有。

與它下面這段代碼發送數據的長度到服務器,因此服務器知道輸入數據的大小,會發生什麼,然後將其發送的實際數據。但是有時例如,它會發送長度比實際發送的數據大,但它發生隨機,害得我也許認爲這是一個線程問題 - 然而byteDataList是這樣一個線程中僅使用,因此它沒有意義對我來說,甚至可以鎖定它。在我測試過的數據中,我發送的數據不超過2kb到17kb。

有誰看到爲什麼這可能是基於從我的項目這個小snipit發生? 此代碼全部爲客戶端注意BitConverter.ToInt32(lengthBuffer, 0)byteDataList[i].Length有望給相同的長度,但事實並非如此。那就是問題所在。從客戶端

List<byte[]> byteDataList = new List<byte[]>(); 
//......... 

lock (byteDataList) //pointless lock, just used for random testing :\ 
{ 
     if (byteDataList.Count > 0) 
     { 
      for (int i = 0; i < byteDataList.Count; i++) 
      { 
       try 
       { 
         byte[] lengthBuffer = BitConverter.GetBytes(byteDataList[i].Length); 
         //quick printout to compare lengths for testing 
         this.QueueOnMainThread(() => 
         { 
         Tools.DebugPrintInGame("Length buffer " + lengthBuffer.Length + 
               + BitConverter.ToInt32(lengthBuffer,0)+ " "+ 
               + byteDataList[i].Length); //this should be same as BitConverter lengthBuffer 
         }); 
         //send length 
         stream.Write(lengthBuffer, 0, lengthBuffer.Length); 
         //send data 
         stream.Write(byteDataList[i], 0, byteDataList[i].Length); 
         stream.Flush(); 
        } 
        catch (Exception ex) 
        { 
         this.QueueOnMainThread(() => 
         { 
          Tools.DebugPrintInGame("Exception " + ex.ToString()); 
         }); 
        } 
      } 

     } 
} 

打印出來之前,它甚至發送到服務器:

Notice different lengths?

通知不同的長度時,最後兩個應該是相同的。 也就是說

`lengthBuffer` = 17672 
`byteDataList[i]` = 17672 

,但有時它會奇怪,靠不住的:

`lengthBuffer` = 17672 
`byteDataList[i]` = 2126 

兩個lengthBuffer和byteDataList [I]應該是相同的。

+0

是,'字節[] Array.Length'會給你的大小以字節數組的字節。 – Euthyphro

+0

是的,然後我發送該數組元素。元素的長度被髮送,然後那個實際元素被髮送。看看代碼,注意[我]? – Euthyphro

+0

爲了調試的目的,我認爲你應該將字節長度加到數據數組的開始處,因爲它的int表示它總是相同的長度,所以你可以在另一端讀取並檢查它們以確保它不是延遲/網絡問題。或者你也看到打印輸出中的斑點? – kmcc049

回答

1

這是最有可能是與封閉了在循環的i變量的問題(我假設你正在使用.NET 4.0或更早版本?)的罪魁禍首是在這裏:

this.QueueOnMainThread(() => 
         { 
         Tools.DebugPrintInGame("Length buffer " + lengthBuffer.Length + 
               + BitConverter.ToInt32(lengthBuffer,0)+ " "+ 
               + byteDataList[i].Length); //this should be same as BitConverter lengthBuffer 
         }); 

看你怎麼引用變量i以上?上面的匿名方法在該變量上形成一個閉包,這意味着在調用該方法之前不對其進行評估。這意味着i的值可能不再是您用來創建lengthBuffer的值,因此您會得到不匹配的結果。

爲了解決這個問題,的i副本存儲到一個變量中的環的內側範圍內,這樣的:

int k = i; 
this.QueueOnMainThread(() => 
          { 
          Tools.DebugPrintInGame("Length buffer " + lengthBuffer.Length + 
                + BitConverter.ToInt32(lengthBuffer,0)+ " "+ 
                + byteDataList[k].Length); //this should be same as BitConverter lengthBuffer 
          }); 

通過關閉在內部範圍變量,它將具有預期值和韓元循環執行時不會改變。這裏的混淆是循環變量實際上被認爲超出了循環體的範圍以達到閉包的目的。在更高版本的C#中(用於.NET 4.5),他們改變了這種行爲,並且循環變量現在被內部作用域關閉。他們做出了這樣的改變,因爲在這種情況下,這個問題很容易被忽略。

+0

是的,使用.net 2.0,謝謝!現在說明爲什麼服務器接收的數據少於預期。 – Euthyphro

+0

@Euthyphro,你等待所有TCP數據包到達的時間足夠長嗎?如果您跨越數據包邊界,單個接收可能無法獲得所有數據,因此必須緩衝並接收數據,直到您有完整的消息。但是,在明確知道大小的情況下,大多數TCP API都會阻止您收到確切的N個字節。 –

+0

在服務器上,我沒有使用.net 2.0,所以我使用'var initialBuffer = new byte [4]; var lengthBuffer = await receiveStream.ReadAsync(initialBuffer,0,4); requestLength = BitConverter.ToInt32(initialBuffer,0);'獲取傳入數據的長度,然後'var bytesRead = await receiveStream.ReadAsync(requestBuffer,0,requestLength);'接收基於期望長度的實際數據。這是我的理解,應該阻止和等待。如果大小不一樣,我會拋出異常。 – Euthyphro

相關問題