Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API

Newsletter sign-up

Sign up for our technology specific newsletters.

Enterprise Java
View all newsletters

Email Address:

Simple handling of network timeouts

Learn just how easy it is to prevent stalled clients and servers

Many programmers dread the thought of handling network timeouts. A common fear is that a simple, single-threaded network client without timeout support will balloon into a complex multithreaded nightmare, with separate threads needed to detect network timeouts, and some form of notification process at work between the blocked thread and the main application. While this is one option for developers, it is not the only one. Dealing with network timeouts need not be a difficult task, and in many cases you can completely avoid writing code for additional threads.

When working with network connections, or any type of I/O device, there are two classifications of operations:

  • Blocking operations: Read or write stalls, operation waits until I/O device is ready
  • Nonblocking operations: Read or write attempt is made, operation aborts if I/O device is not ready

Java networking is, by default, a form of blocking I/O. Thus, when a Java networking application reads from a socket connection, it will generally wait indefinitely if there is no immediate response. If no data is available, the program will keep waiting, and no further work can be done. One solution, which solves the problem but introduces a little extra complexity, is to have a second thread perform the operation; this way, if the second thread becomes blocked the application can still respond to user commands, or even terminate the stalled thread if necessary.

This solution is often employed, but there is a much simpler alternative. Java also supports nonblocking network I/O, which can be activated on any Socket, ServerSocket, or DatagramSocket. It is possible to specify the maximum length of time that a read or write operation will stall before returning control back to the application. For network clients, this is the easiest solution and offers simpler, more manageable code.

The only drawback to nonblocking network I/O under Java is that it requires an existing socket. Thus, while this method is perfect for normal read or write operations, a connect operation can stall for a much longer period, since there is no method for specifying a timeout period for connect operations. Many applications require this ability; you can, however, easily avoid the extra work of writing additional code. I've written a small class that allows you to specify a timeout value for a connection. It uses a second thread, but the internal details are abstracted away. This approach works well, as it provides a nonblocking I/O interface, and the details of the second thread are hidden from view.

Nonblocking network I/O

The simplest way of doing something often turns out to be the best way. While it is sometimes necessary to use threads and blocking I/O, in the majority of cases nonblocking I/O lends itself to a far clearer and more elegant solution. With only a few lines of code, you can incorporate timeout supports for any socket application. Don't believe me? Read on.

When Java 1.1 was released, it included API changes to the java.net package that allowed programmers to specify socket options. These options give programmers greater control over socket communication. One option in particular, SO_TIMEOUT, is extremely useful, because it allows programmers to specify the amount of time that a read operation will block. We can specify a short delay, or none at all, and make our networking code nonblocking.

Let's take a look at how this works. A new method, setSoTimeout ( int ) has been added to the following socket classes:

  • java.net.Socket
  • java.net.DatagramSocket
  • java.net.ServerSocket

This method allows us to specify a maximum timeout length, in milliseconds, that the following network operations will block:

  • ServerSocket.accept()
  • SocketInputStream.read()
  • DatagramSocket.receive()

Whenever one of these methods is called, the clock starts ticking. If the operation is not blocked, it will reset and only restart once one of these methods is called again; as a result, no timeout can ever occur unless you perform a network I/O operation. The following example shows just how easy it can be to handle timeouts, without resorting to multiple threads of execution:

// Create a datagram socket on port 2000 to listen for incoming UDP packets DatagramSocket dgramSocket = new DatagramSocket ( 2000 );
// Disable blocking I/O operations, by specifying a five second timeout dgramSocket.setSoTimeout ( 5000 );


Assigning a timeout value prevents our network operations from blocking indefinitely. At this point, you're probably wondering what will happen when a network operation times out. Rather than returning an error code, which might not always be checked by developers, a java.io.InterruptedIOException is thrown. Exception handling is an excellent way of dealing with error conditions, and allows us to separate our normal code from our error-handling code. Besides, who religiously checks every return value for a null reference? By throwing an exception, developers are forced to provide a catch handler for timeouts.

The following code snippet shows how to handle a timeout operation when reading from a TCP socket:

// Set the socket timeout for ten seconds
connection.setSoTimeout (10000);
try
{
   // Create a DataInputStream for reading from socket
   DataInputStream din = new DataInputStream (connection.getInputStream());
   // Read data until end of data
   for (;;)
   {
      String line = din.readLine();
      if (line != null)
         System.out.println (line);
      else
         break;
   }
}
// Exception thrown when network timeout occurs
catch (InterruptedIOException iioe)
{
   System.err.println ("Remote host timed out during read operation");
}
// Exception thrown when general network I/O error occurs
catch (IOException ioe)
{
   System.err.println ("Network I/O error - " + ioe);
}


With only a few extra lines of code for a try {} catch block, it's extremely easy to catch network timeouts. An application can then respond to the situation without stalling itself. For example, it could start by notifying the user, or by attempting to establish a new connection. When using datagram sockets, which send packets of information without guaranteeing delivery, an application could respond to a network timeout by resending a packet that had been lost in transit. Implementing this timeout support takes very little time and leads to a very clean solution. Indeed, the only time that nonblocking I/O is not the optimal solution is when you also need to detect timeouts on connect operations, or when your target environment does not support Java 1.1.

1 | 2 | 3 | 4 |  Next >
Resources