Search code examples
javamacossocketssleep-mode

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).

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. 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.

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?

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.

Solution

  • IOException means that the local host KNOWS that the remote host is no longer provide data.

    SocketTimeoutException means that the remote host simply failed to provide the data in the time allocated. It never told us that the connection is officially down.

    SocketTimeoutException happens when the connection was not closed gracefully. 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.