Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java socket not throwing exceptions on a dead socket?

We have a simple client server architecture between our mobile device and our server both written in Java. An extremely simple ServerSocket and Socket implementation. However one problem is that when the client terminates abruptly (without closing the socket properly) the server does not know that it is disconnected. Furthermore, the server can continue to write to this socket without getting any exceptions. Why?

According to documentation Java sockets should throw exceptions if you try to write to a socket that is not reachable on the other end!

like image 949
erotsppa Avatar asked Jun 29 '10 22:06

erotsppa


2 Answers

The connection will eventually be timed out by Retransmit Timeout (RTO). However, the RTO is calculated using a complicated algorithm based on network latency (RTT), see this RFC,

http://www.ietf.org/rfc/rfc2988.txt

So on a mobile network, this can be minutes. Wait 10 minutes to see if you can get a timeout.

The solution to this kind of problem is to add a heart-beat in your own application protocol and tear down connection when you don't get ACK for the heartbeat.

like image 179
ZZ Coder Avatar answered Oct 13 '22 18:10

ZZ Coder


The key word here (without closing the socket properly).

Sockets should always be acquired and disposed of in this way:

final Socket socket = ...; // connect code

try
{
    use( socket ); // use socket
}
finally
{
    socket.close( ); // dispose
}

Even with this precautions you should specify application timeouts, specific to your protocol.

My experience had shown, that unfortunately you cannot use any of the Socket timeout functionality reliably ( e.g. there is no timeout for write operations and even read operations may, sometimes, hang forever ).

That's why you need a watchdog thread that enforces your application timeouts and disposes of sockets that have been unresponsive for a while.

One convenient way of doing this is by initializing Socket and ServerSocket through corresponding channels in java.nio. The main advantage of such sockets is that they are Interruptible, that way you can simply interrupt the thread that does socket protocol and be sure that socket is properly disposed off.

Notice that you should enforce application timeouts on both sides, as it is only a matter of time and bad luck when you may experience unresponsive sockets.

like image 22
Alexander Pogrebnyak Avatar answered Oct 13 '22 20:10

Alexander Pogrebnyak