2011-06-28 166 views
-3

我正在將C++客戶端更改爲Java版本 - 僅僅是一個練習,我正在嘗試比其他更多的任務。使用Java客戶端讀取TCP時丟失/丟失數據包

原始C++代碼完美地工作。 Servce端發送一個DWORD,然後客戶端查找它,然後讀取253個字節的數據。我已經在Java中嘗試了這個,取得了很大的成功,客戶端丟棄了大量的數據包,大約有20個數據包通過。下面是我嘗試過的幾個不同的代碼塊。如果有人能告訴我什麼時候出錯,我會非常感激。

感謝

馬克

嘗試1:

 //Create socket connection 
    try 
    { 
     client = new Socket("localhost", 7651); 
     //in = client.getInputStream(); 
     reader = new BufferedReader(new 
       InputStreamReader(client.getInputStream(), "ISO-8859-1")); 
    } 
    catch (UnknownHostException e) 
    { 
     System.out.println("Unknown host: localhost"); 
     System.exit(1); 
    } 
    catch (IOException e) 
    { 
     System.out.println("No I/O"); 
     System.exit(1); 
    } 

    //Receive data from ROS SerialtoNetwork server 

    while (true) 
    { 
     // Read repeatedly until the expected number of chars has been read: 
     char[] buf = new char[300]; 
     int numberRead = 0; 

     int numberToRead = 257; 
     for (int totalCharsRead = 0; totalCharsRead < numberToRead;) 
     { 
      int numberLeft = numberToRead - totalCharsRead; 

      try { 
       numberRead = reader.read(buf, totalCharsRead, numberLeft); 

       if (numberRead < 0) 
       { 
        // premature end of data 
        break; 
       } 
       else 
       { 
        totalCharsRead += numberRead; 
       }    
      } 
      catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 

     String lstr = new String(buf); 
     System.out.print(lstr); 

     System.out.println(""); 
     System.out.println("Bytes Received:" + numberRead); 
    } 

嘗試2:

 //Create socket connection 
    try 
    { 
     client = new Socket("localhost", 7651); 
     in = client.getInputStream();   
    } 
    catch (UnknownHostException e) 
    { 
     System.out.println("Unknown host: localhost"); 
     System.exit(1); 
    } 
    catch (IOException e) 
    { 
     System.out.println("No I/O"); 
     System.exit(1); 
    } 

    //Receive data from ROS SerialtoNetwork server 

    try 
    { 
     while (true) 
     { 
      byte[] cbuf = new byte[300]; 
      int lBytesAvail = in.available();//read(cbuf, 0, 4); 

      if (lBytesAvail > 253) 
      { 
       in.read(cbuf, 0, 4); 
       int lBytesRead = in.read(cbuf, 0, 253); 

       String lstr = new String(cbuf); 
       System.out.print(lstr); 

       System.out.println(""); 
       System.out.println("Bytes Received:" + lBytesRead); 
      } 

     } 
    } 
    catch (IOException e) 
    { 
     System.out.println("Read failed"); 
     System.exit(1); 
    } 
+1

你是什麼意思**客戶端丟失大量的數據包**?您是否在監視網絡流量,並看到實際的數據包被丟棄?或者你的意思是隻讀了20個字節中的一個?這兩個問題是完全分開的,前者可能與硬件有關(或與連接有關),後者可能是代碼中的一個錯誤。 – SRM

回答

0

我試過你的代碼 - 大大減少了fp!仍然是同樣的結果。我用readInt()和只讀257字節(總共包含DWORD)嘗試過看數據,它幾乎總是丟失30/31個數據包 - 可疑!!下面的代碼:

  try 
    { 
     lSocket = new Socket("localhost", 7651); 
     lDataStream = new DataInputStream(lSocket.getInputStream()); 

    } 
    catch (UnknownHostException e) 
    { 
     System.out.println("Unknown host: localhost"); 
     System.exit(1); 
    } 
    catch (IOException e) 
    { 
     System.out.println("No I/O"); 
     System.exit(1); 
    } 

    //Receive data from ROS SerialtoNetwork server 

    try 
    { 
     while(true) 
     { 
      //in.readInt(); 
      byte[] cbuf = new byte[257]; 
      lDataStream.readFully(cbuf);   

      String lstr = new String(cbuf); 
      System.out.print(lstr); 

      System.out.println(""); 
     }    
    } 
    catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

實施例的數據(它是二進制的,第三列是分組SEQ ID - 不能顯示所有的它的一些非打印字符的因此在此示出僅是所述數據的一部分。但我看到當它讀取一個包時全部通過)

ÿþÿ,253,31,26,129,105,94,65,67,31,23,2,9,91,56,12,88,64,2 ,

32-61缺失/未

ÿþÿ,253,62,26129105,94%,65,67,31,23,2,9,5,57,11,88,64讀取2,

63-91缺失/未

ÿþÿ,253,92,26129105,94%,65,67,31,23,2,9,5,57,12,88,64讀取2,

+0

好吧修好了。上面所有的代碼選項都可以工作(Phew!) - 是一個協議錯誤。衛生署!感謝您的建議,但。 – Mark

2

在 「嘗試1」,您打印numberRead,不totalCharsReadnumberRead是最後一次操作讀取的字符數,而不是緩衝區中的總數。您可以儘可能地限制本地變量的範圍,避免過早使用虛擬值對它們進行初始化,從而避免此錯誤。這使得你的代碼更具可讀性。

使用TCP,數據包不會在Java級別被「丟棄」。這是在操作系統級別或以下會發生的事情。 Java運行時中的任何問題都會引發異常。

+0

感謝您的回覆。 Re:打印的數據項數量 - 只是一些調試,我的錯誤。基本上這些數據是從服務器流出的。使用C++客戶端,我可以正確接收所有數據包。 Java中只有20個左右出現約1個。 – Mark

+0

@Mark - 在這兩種情況下都不清楚你如何確定你讀過多少字節。第一,你有一個錯誤,第二,你沒有總結他們,你不提供任何版本的示例輸出。 Java不會丟棄你的數據包;該錯誤在您的代碼中。因此,不要將其視爲理由,*展示*不是:發佈您的實際代碼及其結果。 – erickson

0

如果發件人正在發送二進制數據,您首先會用Reader讀取錯誤的樹。使用DataInputStream.readInt()讀取DWORD,然後使用DataInputStream.readFully()讀取數據。並扔掉所有可怕的循環/計數代碼。