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

如何在计算机唤醒后识别MacOSX上断开的Java套接字连接,java,macos,sockets,sleep-mode,Java,Macos,Sockets,Sleep Mode,我有一个Java客户机,它应该经常连接到某个Java服务器,只输出服务器发送的任何内容(见下面的摘录) 问题是,如果客户端计算机(MacOS X)进入睡眠状态,然后再次醒来,客户端将挂起在.readLine()中的in,并且没有意识到连接已断开。我在套接字中添加了一个SO_TIMEOUT,这样客户端就可以停止阻塞readLine(),它确实会抛出一个SocketTimeoutException,但随后很高兴再次尝试从断开的连接中读取一行 我的问题是:为什么.readLine()中的不会因IOEx

我有一个Java客户机,它应该经常连接到某个Java服务器,只输出服务器发送的任何内容(见下面的摘录)

问题是,如果客户端计算机(MacOS X)进入睡眠状态,然后再次醒来,客户端将挂起在.readLine()中的
in
,并且没有意识到连接已断开。我在套接字中添加了一个
SO_TIMEOUT
,这样客户端就可以停止阻塞
readLine()
,它确实会抛出一个
SocketTimeoutException
,但随后很高兴再次尝试从断开的连接中读取一行

我的问题是:为什么.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()));
    }
}

如果需要使用超时并在套接字断开时重新连接,请尝试以下操作:

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
在连接未正常关闭时发生。如果远程主机电源断开,或者有人从中拔出以太网电缆,这就是你得到的

在本例中,当您处于睡眠状态时,远程主机必须已决定关闭连接,但您的主机由于处于睡眠状态而错过了通知


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

IOException
表示本地主机知道远程主机不再提供数据

SocketTimeoutException
表示远程主机无法在分配的时间内提供数据。它从未告诉我们连接正式中断

SocketTimeoutException
在连接未正常关闭时发生。如果远程主机电源断开,或者有人从中拔出以太网电缆,这就是你得到的

在本例中,当您处于睡眠状态时,远程主机必须已决定关闭连接,但您的主机由于处于睡眠状态而错过了通知


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

问题在于从不抛出
IOException
。它只是抛出
SocketTimeoutException
,然后一遍又一遍地尝试读取一行。即使我在另一端终止服务器,客户端仍会尝试读取一行(而不会抛出
IOException
)。您可以尝试ping此连接。尝试向服务器发送简单数据。如果成功,则连接处于活动状态,否则关闭套接字并在我的第二个catch块中执行代码。您可以检查socket.isConnected(),但我不确定它是否有帮助。问题是从未抛出
IOException
。它只是抛出
SocketTimeoutException
,然后一遍又一遍地尝试读取一行。即使我在另一端终止服务器,客户端仍会尝试读取一行(而不会抛出
IOException
)。您可以尝试ping此连接。尝试向服务器发送简单数据。如果成功,则连接处于活动状态,否则关闭套接字并执行第二个catch块中的代码。您可以检查socket.isConnected(),但我不确定它是否有帮助。