2017-04-12 83 views
2

我有一個Java客戶端應該不斷連接​​到某個Java服務器,並輸出任何服務器發送的內容(請參閱下面的摘錄)。如何識別計算機喚醒後在MacOSX上損壞的Java套接字連接

問題是,如果客戶端計算機(MacOS X)進入休眠狀態,然後再次喚醒,客戶端掛起在in.readLine(),並沒有意識到連接中斷。我向套接字添加了一個SO_TIMEOUT,以便客戶端在readLine()上停止阻塞,並且確實拋出了SocketTimeoutException,但是然後愉快地嘗試再次從斷開的連接中讀取一行。

我的問題是:爲什麼不in.readLine()失敗,並IOException(這樣我就可以重新啓動連接),我怎樣才能使客戶端重新連接到服務器上的awake->sleep->awake週期在Mac OS X?

Socket socket = new Socket(...); 
socket.setSoTimeout(10000); 
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
[...] 
while (true) { 
    try { 
     while ((serverSays = in.readLine()) != null) { 
      System.out.println("Server says: " + serverSays); 
     } 
    } catch (SocketTimeoutException e) { 
     continue; 
    } 
    // An exception other than SocketTimeoutException will break the while-loop. 
} 
// If another exception other than SocketTimeoutException occurs, 
// catch it and re-initiate the connection and start over. 

回答

0

IOException意味着本地主機知道遠程主機不再提供數據。

SocketTimeoutException意味着遠程主機根本無法在分配的時間內提供數據。它從未告訴我們該連接正式停止。

SocketTimeoutException當連接沒有正常關閉時發生。如果遠程主機電源中斷,或者有人將以太網電纜從中拔出,那就是您所得到的。

在這種情況下,當您睡覺時,遠程主機必須決定關閉連接,但您的主機錯過了正在睡覺的通知。

解決的辦法是假定連接在超過一定數量的超時後死亡。

-1

如果您需要使用超時和重新連接,如果插座壞了,試試這個:

Socket socket = new Socket(...); 
socket.setSoTimeout(10000); 
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
[...] 
while (true) { 
    try { 
     while ((serverSays = in.readLine()) != null) { 
      System.out.println("Server says: " + serverSays); 
     } 
    } catch (SocketTimeoutException e) { 
     continue; 
    } catch (IOException e) { 
     //reconnecting with new Socket object and new reader, because old stream closed 
     socket = new Socket(...); 
     socket.setSoTimeout(10000); 
     in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
    } 
} 
+0

問題是'IOException'永遠不會被拋出。它只是拋出'SocketTimeoutException',然後嘗試再次讀取一行,一遍又一遍。即使我殺死另一端的服務器,客戶端仍會嘗試讀取一行(不拋出'IOException')。 –

+0

您可以嘗試ping此連接。嘗試發送簡單的數據到服務器。如果成功,那麼連接是活着的,否則關閉套接字並在我的第二個catch塊中執行代碼。 –

+0

你可以檢查socket.isConnected(),但我不確定它是否有幫助。 –