How can my program tell when a socket connection is broken when it is using stream classes to read/write to the socket?

Tim Rohaly

The only ways to know a connection is broken abnormally (indeed, the definitions of a broken connection), are:

  • you send a packet and fail to get a reply within a "reasonable" time
  • you try to read a packet and fail to receive data within a "reasonable" time
Where "reasonable" is an application-specific concept.

(The TCP KEEP_ALIVE feature uses polling in the transport layer to periodically check the connection in this manner.)

You could just catch the exception thrown when you try to read or write, but the problem with that is the socket streams are buffered, so if there is data in the local buffer, it is possible to read from a socket even though the network is down or the server is not responding. An exception won't be thrown until you've exhausted the buffer and need to go out over the net to refill it. Catching the exception will certainly detect a broken connection, eventually. But it might be long after the server goes down.

The buffer is in the transport layer, which is implemented by the OS and not by any Java or native code. Packets that are received by the transport layer need to be buffered for use by the application layer. JDK 1.1+ gives you some socket options which affect the transport layer, for example setSoLinger(). JDK 1.3 gives more control over the options, including buffering, through the Socket methods setSendBufferSize(), setReceiveBufferSize(), etc.

It stands to reason that no less than an entire packet must be received, even though the application may only be requesting a few bytes. TCP must buffer the unused data. Likewise, on sending, TCP tries to aggregate small packets for efficiency - you have some control over this through setTcpNoDelay().

Of course a Socket could also be shut down deliberately, in which case a negotiated end to the TCP session takes place and you find this out immediately (an IOException might be thrown, for instance).