I have some code that opens a socket, sends a message, receives a response, and closes the socket. I need to add a timeout to shut down the socket connection if it takes longer than a specified duration. This code is written in Java, but this is a design question.
Sockets support a read timeout. To see how it works, read about setSoTimeout()
in the Javadoc for java.net.Socket
, or try man 2 getsockopt
on your local Unix machine. All socket implementations provide this same timeout functionality.
Anyway, the way the read timeout works is that you can set how long the socket will wait without receiving data before the connection is automatically terminated. If I open a socket connection with a 5000 millisecond read timeout, and the other end of the connection sends me no data before 5 seconds elapses, the connection will be dropped. In Java, this results in a SocketTimeoutException
being thrown.
This timeout is somewhat useful, but only in limited circumstances because the timer only begins once the connection is established (and is automatically restarted as soon as the socket stops receiving data from the other end of the connection). If a network issue prevents the socket connection from completing but doesn’t block the attempt to connect outright, the timeout counter never starts, and the connection just hangs indefinitely. You see this sort of thing happen sometimes when you try to connect to a server via SSH. If there’s a network issue, the connection will hang without being dropped. On the other hand, if you connect and don’t enter your password, the server will drop your connection after awhile due to inactivity. That’s the socket’s read timeout kicking in.
Anyone know the best approach for timing out when you attempt to connect and are unable to do so? I haven’t found any solutions in my research, although I do confess that I have not looked at any of the Stevens books yet.
November 27, 2007 at 11:33 pm
This is the point where I give up, and don’t use the socket-level options.
Write a wrapper class as a gateway for all your network access needs, using your own timers. j.u.Timer and j.u.concurrent are your new friends.
November 28, 2007 at 5:30 am
“I have some code that opens a socket, sends a message, receives a response, and closes the socket.”
Isn’t that a prime description of what RFC 2616, aka HTTP, does? So why not just use HTTP?
November 28, 2007 at 9:28 am
I don’t use HTTP because the end point is not an HTTP service, it’s a socket you can connect to. (If both ends of the connection were under my control, I’d use HTTP.)
That said, you run into exactly the same problem with most HTTP libraries. If the connection fails to complete, they don’t time out. I expect that’s because most HTTP libraries use the socket read timeout feature built into the network libraries they use.
November 28, 2007 at 2:24 pm
Threading to the rescue!
*) The thread has to connect before a certain amount of time and then indicate that it is “okay” upon success.
*) If the “okay notification” is not received in time, the thread is killed.
*) Otherwise it is allowed to live, for now. Maybe. 🙂
November 28, 2007 at 3:26 pm
Am I wrong to worry about overhead when creating these threads?
November 28, 2007 at 7:21 pm
I believe that java NIO is the “correct” way to do this, although you might not want to invest in learning it if this is a small non-recurring problem. I’d solve it using 2 threads and non-blocking sockets [selector.select(TIMEOUT)].