Java Exception Handling

Java Exception Handling – SocketTimeoutException

Making our way through our in-depth Java Exception Handling series, today we’ll be going over the SocketTimeoutException. As you may suspect based on the name, the SocketTimeoutException is thrown when a timeout occurs during a read or acceptance message within a socket connection.

Throughout this article we’ll explore the SocketTimeoutException in more detail, starting with where it resides in the overall Java Exception Hierarchy. We’ll then look at some functional sample code that will illustrate how a common socket connection might be established, and how failure to plan ahead for potential connection timeouts can lead to unexpected SocketTimeoutExceptions. Let’s get this party started!

The Technical Rundown

All Java errors implement the java.lang.Throwable interface, or are extended from another inherited class therein. The full exception hierarchy of this error is:

Full Code Sample

Below is the full code sample we’ll be using in this article. It can be copied and pasted if you’d like to play with the code yourself and see how everything works.

This code sample also uses the Logging utility class, the source of which can be found here on GitHub.

When Should You Use It?

A SocketTimeoutException can really occur under only a handful of circumstances (at least, while using the standard Java libraries). All of these scenarios occur when dealing directly with the Socket class, which allows for client sockets to be established to remote endpoints. In other words, Sockets are used to establish connections between two systems, including the common client and server configuration that’ll be using today in our example code.

To begin we’ll need the Server class:

The Server class file also includes a main(...) method so we can easily execute the server creation process in a separate thread from our client code, which we’ll look at in a moment. Overall, the server is established by creating a new ServerSocket instance, associated with the specified port. We then enter a constant loop listening for incoming socket connections and printing out a stream with the data message sent by the client, if applicable. This process repeats until the connection is lost or an error occurs.

Meanwhile, our Client class is slightly more complex, but still fairly simple:

The Connect(String host, int port, int timeout, boolean shouldSleep) method overload is where most of the logic occurs, but we’ve also added a number of other Connect(...) method overloads for simplicity and usability, relying on a handful of default property values for things like the host, port, and timeout period. Just as with our server code, the Client connection process creates an infinite loop in which it establishes a new Socket, then attempts a direct connection to the specified host and port. Critically, we’re also passing the second parameter to the Socket.connect(...) method, which indicates the timeout period (in milliseconds) that the connection is allowed before timing out.

Once a connection is established the client creates a reader and writer, which we use to send and receive data messages between the server. The client can write messages in the console, which are sent to the server and the server will respond to the client, in kind. Sending quit or exit will close the connection and exit the loop.

To test things out we start with a baseline connection test. First we must initialize our Server:

As expected, this outputs a confirmation indicating the server is up and running:

Now, we’ll begin with a basic client connection using our default parameters:

The client output shows that a connection was established and the server sends a message prompting us for some input:

Let’s just say “hello” to the server, which outputs the following for the client:

Meanwhile, the server receives the message and outputs this;

Cool. Everything seems to be working as expected. If we type exit or quit we’ll close the client connection and can move onto the next test:

Our next Connect(...) method call includes a 1 millisecond timeout:

Normally, 1 millisecond is an exceptionally inadequate timeout period. However, since both the client and server are running locally in our development setup, running this code will usually not result in any problems. As we see here, we were able to connect without experiencing a timeout, and successfully sent another message to the server:

To simulate an actual delayed network connection we’ll lastly try adding an explicit pause during our connection process by calling Thread.sleep(...) within the Connect(...) method:

Executing this code will typically throw a SocketTimeoutException our way, indicating that the connection could not be established within the extremely short one millisecond timeout period:

The Airbrake-Java library provides real-time error monitoring and automatic exception reporting for all your Java-based projects. Tight integration with Airbrake’s state of the art web dashboard ensures that Airbrake-Java gives you round-the-clock status updates on your application’s health and error rates. Airbrake-Java easily integrates with all the latest Java frameworks and platforms like Spring, Maven, log4j, Struts, Kotlin, Grails, Groovy, and many more. Plus, Airbrake-Java allows you to easily customize exception parameters and gives you full, configurable filter capabilities so you only gather the errors that matter most.

Check out all the amazing features Airbrake-Java has to offer and see for yourself why so many of the world’s best engineering teams are using Airbrake to revolutionize their exception handling practices!