2016-04-14 61 views
2

我有一個多線程TCP套接字偵聽器程序。我對一個特定的字節數(128字節和4x多個)的數據進行了阻塞讀取,所以我的數據包大小是128字節,256字節,384字節和512字節。TCP套接字數據獲取加擾

我有問題,因爲有時候數據在插座中變得混亂。對於如:

應該閱讀:

<header><data payload(padded with zeros to compensate size)><footer> 

ex-- ABCDddddddddd0000000000WXYZ

我有時讀什麼:

ex-- ABCDdd00000000000000000dddddd00

,然後下一個數據包看起來像

00000WXYZABCDddddd00000000000000000

,所以我關閉套接字,我們已經定義了協議來發送回2個或3舊數據包,以避免損失。

我的問題是

1.爲何數據得到炒/搞砸?

2.是否可以通過任何方式避免?

這裏是我讀取數據的代碼。

in = new DataInputStream(conn.getInputStream()); 
outStream = conn.getOutputStream(); 
while (m_bRunThread) { 
    // read incoming stream 
    in.readFully(rec_data_in_byte, 0, 128); //blocks until 128 bytes are read from the socket 
    { 
     //converting the read byte array into string 
     //finding out the size from a particular position,helps determine if any further reads are required or not. 
     //if the size is a multiple of 128 and the size is a multiple higher than 1 then more reads are required. 
     if ((Integer.parseInt(SIZE) % 128 == 0) && ((SIZE/128) > 1)) { 
      for(int z = 1;z < lenSIZE;z++) { 
       in.readFully(rec_data_in_byte1, 0, 128);//changed from in.read(rec_data_in_byte1, 0, 128); as per suggestions 
      } 
      //extracting the data,validating and processing it 
     } 
    } 
} 

UPDATE: 實現彼得斯修復,但問題仍然存在。數據越來越亂。 在字節數組轉換爲字符串的地方添加幾行額外的代碼。

byte[] REC_data=new byte[1024]; 
System.arraycopy(rec_data_in_byte1, 0, REC_data, 128*z, 128); 
rec_data_string=MyClass2.getData(REC_data,0,Integer.parseInt(SIZE)-1,Integer.parseInt(SIZE)); 

的getData()方法是如下:

String msg = "";//the return String 
    int count = 1; 
    for (int i = 0; i < datasize; i++) { 
     if (i >= startindex) { 
      if (count <= lengthofpacket) { 
       msg += String.valueOf((char) (bytedata[i])); 
       count++; 
      } 
     } 
    } 
    return msg; 

可以任何這是用於加擾的原因嗎?

P.S - 爭奪的方式與之前發生的一樣。

+2

我回滾了上次的編輯。您的修改使Peter Lawrey給出的答案失效。如果你遵循了彼得的建議,那麼要麼提出一個新問題,要麼更新你的問題來**添加**你嘗試過的新事物和你所看到的。請注意,您應該也包含用於編寫數據的代碼。問題可能就在那裏。 –

+0

@Mark Rotteveel-感謝您的建議。將從現在開始做。新的到stackoverflow的世界.. –

+0

所有的更新和回滾後,你仍然有一個'read()'方法的返回值,你沒有使用。你需要在任何地方使用'readFully()',或者不要假設'read()'填充緩衝區的適當代碼。 TCP是一個字節流,沒有義務一次傳送多個字節。 – EJP

回答

2

當你

int lengthActuallyRead = in.read(rec_data_in_byte1, 0, 128); 

您需要檢查讀取的長度。否則,它可能會讀取1個字節,或者在這種情況下讀取最多128個字節。請注意,實際讀取的內容之後的任何字節都是未觸及的,因此它們可能是0,或者它們可能是垃圾留在先前的消息中。

如果你希望128個字節你可以使用readFully像你一樣以前

in.readFully(rec_data_in_byte, 0, 128); 

注意:如果剩餘量小於128你可能想這樣做。

int remaining = size - sizeReadSoFar; 
int length = in.read(rec_data_in_byte1, 0, remaining); 

這會阻止您在閱讀舊信息時閱讀下一部分信息。

+0

我的協議是設計在客戶端發送數據包只有128字節和多達4,所以讀取的數據將永遠是128和它的倍數。現在編輯代碼現在**讀**現在是**讀**,所以它的目的。 –

+0

但仍然是我的問題仍然可以數據混亂/雜亂? –

+0

@JayeshTripathi數據在網絡上沒有損壞,但是如果你沒有正確讀取它,它可能會被損壞。 –