2015-05-09 51 views
0

現在,我正在嘗試編寫一個基於GUI的基於網絡連接的Java井字遊戲。它基本上在這一點上工作,但我有一個間歇性的錯誤,其中通過網絡連接發送的幾個字符在遊戲過程中丟失。一種情況下看起來像這樣,當println語句被添加到消息發送/讀取:最後幾個字符串通過套接字發送有時在Java網絡程序中丟失

播放機1: 剛剛發送ROW 14 COLUMN 11 GAMEOVER真

玩家2: 剛收到ROW 14 COLUMN 11 GAMEOV

林相當肯定,當我通過網絡閱讀時發生錯誤。讀發生在自己的線程,與周圍的套接字的InputStream的包裹一個BufferedReader,看起來像這樣:

try { 
     int input; 
     while((input = dataIn.read()) != -1){ 
      char msgChar = (char)input; 
      String message = msgChar + ""; 
      while(dataIn.ready()){ 
       msgChar = (char)dataIn.read(); 
       message+= msgChar; 
      } 
      System.out.println("Just received " + message); 
      this.processMessage(message); 

     } 
     this.sock.close(); 


    } 

我的sendMessage方法是非常簡單的,(只是在圍繞插座的OutputStream的包裹DataOutputStream類寫入)所以我不認爲問題在那裏發生:

try { 
     dataOut.writeBytes(message); 
     System.out.println("Just sent " + message); 
    } 

任何想法將不勝感激。謝謝!

+0

是否有可能數據沒有完全刷新並且沒有被其他線程完整接收?你有證實嗎? –

回答

1

事實證明,ready()方法只能保證下一次讀取不會被阻塞。因此,!ready()不會擔心下一次讀取會阻塞。只是它可以。

我相信這裏的問題必須與TCP堆棧本身有關。面向數據流,當字節被寫入套接字時,TCP不保證它發送的字節的順序或分組。我懷疑TCP堆棧以一種有意義的方式分解了發送的字符串,並且在這個過程中,ready()方法必須檢測到流中某種基本的中斷,並返回false,儘管有更多信息可用的事實。

我重構了爲每條消息發送添加一個換行符的代碼,然後簡單地執行readLine()代替。這使我的網絡協議依賴於換行符作爲消息分隔符,而不是ready()方法。我很高興地說這解決了這個問題。

感謝您的所有意見!

2

嘗試刷新發件人端的OutputStream。最後的字節可能保留在一些內部緩衝區中。

+0

我只是嘗試添加dataOut.flush()到上面的sendMessage方法,刷新DataOutputStream。不幸的是,這似乎並沒有緩解這個問題。添加這一行後,我在運行程序時剛剛得到以下輸出:播放器1 ---剛剛發送ROW 24 COL 19 GAMEOVER false。玩家2 ---剛剛收到ROW 24 COL 19 GAMEOVER。注意收到的信息中缺少「false」... - –

0

用什麼類型的流對象來處理數據是非常重要的。在我看來,這種故障排除是由於您使用DataOutputStream發送信息,但接收其他信息而創建的。嘗試分別通過DataOutputStream和DataInputStream發送和接收信息。

物質事實上,如果你通過調用dataOut.writeBoolean送東西(B) 而是試圖通過調用dataIn.readString接受這件事情(),你最終會得到什麼。 DataInputStream和DataOutputStream是類型敏感的。試着重構你的代碼,記住它。

此外,一些輸入流返回調用read()單個字節。在這裏你試着將這個一個單一的字節轉換成char,而在java中默認的char由兩個字節組成。

 msgChar = (char)dataIn.read(); 

檢查是否是數據丟失的原因。

+0

感謝您的建議!出於好奇,我嘗試重構我的代碼的副本,以便使用DataInputStream進行讀取,並使用DataOutputStream進行寫入(這需要使用DataInputStream的availible()方法來代替BufferedReader的ready())。不幸的是,當使用DataInputStream時,這個錯誤似乎仍然存在,我懷疑是因爲我在我的答案中推測出類似的原因。另外,我相信BufferedReader的read()方法返回流中char的下16位,填充到32位整數中。 –

+0

@ user3538431在此處發佈您的代碼 –