计算机唤醒后如何在 MacOS 上识别断开的 Java 套接字连接
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
而失败(以便我可以重新启动连接)以及如何让客户端重新连接到服务器在 Mac OS X?
上的 awake->sleep->awake
循环
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.
如果你需要使用超时并在套接字损坏时重新连接,试试这个:
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()));
}
}
IOException
表示本地主机知道远程主机不再提供数据。
SocketTimeoutException
表示远程主机根本未能在分配的时间内提供数据。它从未告诉我们连接已正式断开。
SocketTimeoutException
当连接未正常关闭时发生。如果远程主机电源没电了,或者有人拔掉了以太网电缆,那就是你得到的结果。
在这种情况下,当你在睡觉时,远程主机肯定决定关闭连接,但你的主机错过了通知,正在睡觉。
解决方案是假设连接在一定次数的超时后断开。
我有一个 Java 客户端,它应该持续连接到某个 Java 服务器,并且只输出服务器发送的任何内容(请参阅下面的摘录)。
问题是如果客户端计算机 (MacOS X) 进入休眠状态然后再次醒来,客户端挂在 in.readLine()
并且没有意识到连接断开。我向套接字添加了一个 SO_TIMEOUT
,这样客户端就不会在 readLine()
上阻塞,它确实抛出了一个 SocketTimeoutException
,但随后很高兴再次尝试从断开的连接中读取一行。
我的问题是:为什么 in.readLine()
不会因 IOException
而失败(以便我可以重新启动连接)以及如何让客户端重新连接到服务器在 Mac OS X?
awake->sleep->awake
循环
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.
如果你需要使用超时并在套接字损坏时重新连接,试试这个:
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()));
}
}
IOException
表示本地主机知道远程主机不再提供数据。
SocketTimeoutException
表示远程主机根本未能在分配的时间内提供数据。它从未告诉我们连接已正式断开。
SocketTimeoutException
当连接未正常关闭时发生。如果远程主机电源没电了,或者有人拔掉了以太网电缆,那就是你得到的结果。
在这种情况下,当你在睡觉时,远程主机肯定决定关闭连接,但你的主机错过了通知,正在睡觉。
解决方案是假设连接在一定次数的超时后断开。