[英]How to recognize broken Java socket connection on MacOSX after computer wakeup
我有一個Java客戶端,該客戶端應該一直連接到某些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.
IOException
意味着本地主機知道遠程主機不再提供數據。
SocketTimeoutException
意味着遠程主機根本無法在分配的時間內提供數據。 它從未告訴我們連接已正式斷開。
當未正確關閉連接時,會發生SocketTimeoutException
。 如果遠程主機電源中斷,或者有人將以太網電纜從中拔出,那就可以了。
在這種情況下,當您處於睡眠狀態時,遠程主機必須已決定關閉連接,但是您的主機卻在睡眠中錯過了通知。
解決方案是假設經過一定數量的超時后連接已死。
如果您需要使用超時並在套接字斷開時重新連接,請嘗試以下操作:
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()));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.