Java Exception Handling

Java Exception Handling – SocketException

Making our way through our in-depth Java Exception Handling series, today we’ll be going over the SocketException. As the name suggests, a SocketException occurs when a problem occurs while trying to create or access a Socket.

Throughout this article we’ll examine the SocketException in more detail, starting with where it sits in the overall Java Exception Hierarchy. We’ll then look at some functional sample code that will illustrate how a typical socket connection can be established, and how how connectivity issues between client/server can produce unexpected SocketExceptions, so let’s begin!

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?

The SocketException is similar to the SocketTimeoutException we explored last month, but, believe it or not, SocketTimeoutException is not inherited from the broader SocketException class. Instead, SocketTimeoutException — which indicates a timeout occurred during a read or acceptance message within a socket connection — inherits from java.io.InterruptedIOException, which itself inherits from java.io.IOException (the same parent class used by SocketException). In practical terms, this means that SocketException is usually indicative of a more generic connection issue, while SocketTimeoutException is explicitly thrown only when timeout problems occur.

To illustrate how a SocketException can commonly occur we’ll start with a simple client/server configuration, similar to that we used in a previous post. We run the test by running both the client and server on separate threads, then the server will prompt the client to enter a message. Once the client enters a message, that value is transferred to and received by the server, before the server then prompts for a new message. This repeats until the client gracefully ends the connection.

We’ll start by looking at the Server.java class:

Executing the Server.main() method invokes CreateServer(int port) and creates a ServerSocket(int port) and the DefaultPort of 24601. The server socket accepts incoming connections on that port, creates a PrintWriter using an output stream to send a prompt message to the client. Once sent, the server creates a new InputStreamReader from the input stream coming from the client, then reads and outputs the message the client sent. A continuous while loop is used to repeat this whole process over and over, awaiting a connection, prompting for input, and outputting the received input from the client.

Meanwhile, here’s the Client.java class:

The Client.main() method creates a new Client instance, which invokes Connect(...) two times. The first invocation uses default values (including port 24601), while the second connection does the same but with a very short 1 ms timeout period. Otherwise, functionality of Client.Connect(...) is rather similar to Server.CreateServer(int port). It begins by establishing a new Socket instance and connecting to the proper host (localhost), port, and using the passed timeout value. An InputStreamReader is used to get the input stream from the server, which is output to the client. The client is then prompted to send a message, which is passed to the server. If the client enters quit or exit keywords, the socket connection is closed. Meanwhile, another while loop repeats thie entire process over and over.

If we test this out we start by running Server.java, then Client.java afterward. The server outputs:

And the client outputs after entering “Hello” at the prompt:

Everything is working as expected. But, what happens if we interrupt the client connection in some way, such as terminating the process? Immediately the server experiences a problem and catches the thrown SocketException:

This shouldn’t be much of a surprise that closing the client connection produces an error on the server. However, what happens if we reverse the process and terminate the server process while connected? As it happens, the client prompt remains open and awaits input from the user, due to these code statements:

Execution halts while awaiting for user input. However, as soon as a message is entered the client recognizes that the server has disconnected, so the client now throws a SocketException when execution resumes:

The Client constructor invokes a second Client.Connect(...) call after the first, so now that the server has been terminated, the second attempt by the client to establish a new Socket connection results in a SocketTimeoutException, since no connection could be established to the server:

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!