I've got Java code which makes a long term socket connection to a home automation device to monitor it for activity/events. The problem is if the device is rebooted or gets power cycled the Java code should automatically reconnect as soon as possible. Any ideas for how to detect a dropped connection on the Java side, preferably without periodic polling the device?

3 Answers
3

If the device reboots without properly closing the socket, I don't know of anything that will allow you to detect it. Your server will not be able to detect that the socket has gone away, in this case, unless the device comes back up or until the TCP/IP stack on your server gives up and declares the connection is dead. At some point you'll get an IOException. You need to catch that Exception and then reconnect when it occurs.

You're really at the mercy of the behavior of TCP/IP here. When one end of a connection simply disappears (no FIN packet), the other end may wait an arbitrary length of time (depending on many factors) before deciding the connection is dead.

If you want to catch this problem earlier -- and you can guarantee that the device will respond within a set amount of time, then set a timeout on the socket. If you do this, you'll get a SocketTimeoutException if the device doesn't respond, and you can then close the socket and try reopening the socket. I have used this with success.

If your software is just waiting for data from the home automation device the only way to detect that the device is gone is to enable the SO_KEEPALIVE option in the socket open to communicate with the device.

To do this just call setKeepAlive(true) method on the socket and that will make the underlying socket implementation enable the SO_KEEP_ALIVE option.

This will make the underlying implementation periodically exchange some data with the remote endpoint and if the device dies while you are waiting for data, an exception will be thrown.

The only problem is that this keep alive time-out depends on the operating system and sometimes cannot be changed.

If you need shorter timeouts, there's no other way than implementing a periodic probe on the device.

If you want to catch this problem earlier -- and you can guarantee that the device will respond within a set amount of time, then set a timeout on the socket. If you do this, you'll get a SocketTimeoutException if the device doesn't respond, and you can then close the socket and try reopening the socket. I have used this with success.

Quoted from above:

I get it to close the socket then attempt to reopen it, which it runs
that code fine. The only problem is that once I close a socket I
cannot reopen it, I get the exception that the socket is closed. This
happens every time. How do I close a socket then reopen it with out
getting this exception?