First, it's important to understand that you actually need to timeout two separate processes - the DNS lookup, and the connection itself. If both have to fit within a certain timeout, then the solution has to look something like this:
long startTime = System.currentTimeMillis();
InetAddress destination = doDnsLookupWithTimeout(MAX_TIMEOUT);
long remaniningTime = MAX_TIMEOUT - (System.currentTimeMillis() - startTime);
if (remainingTime > 0){ //we still have time to connect
connectWithTimeout(remainingTime);
}
The good news is that it's easy to timeout the socket connection, you've already done that. The bad news however is that enforcing a timeout on the DNS lookup is harder. Unfortunately, Java's InetAddress.getByName()
doesn't accept a timeout parameter, so the call can block for a quite a while (I recently had an issue with some reverse DNS calls on windows blocking for 4.5 seconds).
One solution is to simply to avoid Java's native DNS lookup utilities, and use an external library that supports timeout for instance, DnsJava's SimpleResolver which has a setTimeout() method.
Another solution that comes to mind is to perform the DNS lookups in a separate thread, and wait for that thread to finish its business using Thread.join() or Future.get() with a timeout value. If the second thread finishes in time, use the remaining time to connect. If it doesn't, and you timeout on the Thread.join
or Future.get
, then you've timeout out.