简体   繁体   English

唤醒计算机后如何识别MacOSX上断开的Java套接字连接

[英]How to recognize broken Java socket connection on MacOSX after computer wakeup

I have a Java client that is supposed to be constantly connected to some Java server and just output whatever the server sends (see excerpt below). 我有一个Java客户端,该客户端应该一直连接到某些Java服务器,并且仅输出服务器发送的所有内容(请参见下面的摘录)。

The problem is that if the client computer (MacOS X) goes to sleep and then wakes up again, the client hangs at in.readLine() and does not realize that the connection is broken. 问题在于,如果客户端计算机(MacOS X)进入睡眠状态,然后再次唤醒,则客户端将挂在in.readLine()而不会意识到连接已断开。 I added a SO_TIMEOUT to the socket so that the client would stop blocking on readLine() , and it indeed throws a SocketTimeoutException , but then happily tries to read a line from the broken connection again. 我向套接字添加了SO_TIMEOUT ,以便客户端可以停止在readLine()上进行阻塞,并且确实会引发SocketTimeoutException ,但是随后很高兴再次尝试从断开的连接中读取一行。

My questions are: Why doesn't the in.readLine() fail with an IOException (so that I can re-initiate the connection) and how can I make the client reconnect to the server on a awake->sleep->awake cycle on Mac OS X? 我的问题是:为什么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 means that the local host KNOWS that the remote host is no longer provide data. IOException意味着本地主机知道远程主机不再提供数据。

SocketTimeoutException means that the remote host simply failed to provide the data in the time allocated. SocketTimeoutException意味着远程主机根本无法在分配的时间内提供数据。 It never told us that the connection is officially down. 它从未告诉我们连接已正式断开。

SocketTimeoutException happens when the connection was not closed gracefully. 当未正确关闭连接时,会发生SocketTimeoutException If remote host power supply dies, or someone yanks the Ethernet cable out of it, that's what you get. 如果远程主机电源中断,或者有人将以太网电缆从中拔出,那就可以了。

In this case, while you were sleeping, the remote host must have decided to close the connection, but your host missed the notification, being asleep. 在这种情况下,当您处于睡眠状态时,远程主机必须已决定关闭连接,但是您的主机却在睡眠中错过了通知。

The solution would be to assume the connection is dead after certain number of timeouts. 解决方案是假设经过一定数量的超时后连接已死。

If you need to use timeout and reconnect if socket broken, try this: 如果您需要使用超时并在套接字断开时重新连接,请尝试以下操作:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM