[英]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.