计算机唤醒后如何在 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 当连接未正常关闭时发生。如果远程主机电源没电了,或者有人拔掉了以太网电缆,那就是你得到的结果。

在这种情况下,当你在睡觉时,远程主机肯定决定关闭连接,但你的主机错过了通知,正在睡觉。

解决方案是假设连接在一定次数的超时后断开。