Blog |

How to Handle the Socket Exception in Java

How to Handle the Socket Exception in Java
Table of Contents

The SocketException is an exception in Java that is thrown to indicate that an error was encountered while creating or accessing a Socket.

Since the SocketException is a checked exception, it either needs to be thrown or surrounded by a try-catch block in code.

 

What Causes SocketException

SocketException is a subclass of IOException and is the most general exception that indicates a problem when trying to open or access a socket. Some common causes for the SocketException are:

  • Closed socket connection - The most common cause of SocketException is reading or writing from or to a closed socket connection. It can also occur when the connection is closed before all the data is read in the socket buffer.
  • Slow network - A poor network connection might also cause a SocketException. Setting a higher connection timeout can decrease the rate of SocketException for slow connections.
  • Network firewall - A network firewall can close socket connections. A network monitoring tool like Wireshark can be used to check firewall activities.
  • Idle connection - Long idle connections might also cause a SocketException. If a connection needs to be used for a long time, heartbeat messages can be sent to prevent the idle state.
  • Errors in code - A SocketException can also occur because of issues or bugs in code. For example, if a client sends a message to the server after the socket connection is closed.

 

SocketException Example

The following is an example of a SocketException thrown when trying to write to a closed socket connection. Two classes, MyServer and MyClient are created to illustrate this.

MyServer.java:

public class MyServer {
    public static void main(String[] args) throws InterruptedException {
        new Thread(new Server()).start();
    }

    static class Server implements Runnable {
        @Override
        public void run() {
            ServerSocket serverSocket = null;

            try {
                serverSocket = new ServerSocket(4444);

                while (true) {
                    try {
                        Socket clientSocket = serverSocket.accept();

                        BufferedReader inputReader = new BufferedReader(
                                new InputStreamReader(clientSocket.getInputStream()));
                        System.out.println("Message from client: " + inputReader.readLine());
                    } catch (SocketTimeoutException ste) {
                        ste.printStackTrace();
                    }
                }
            } catch (IOException ioe) {
                ioe.printStackTrace();
            } finally {
                try {
                    if (serverSocket != null) {
                        serverSocket.close();
                    }
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
    }
}

Executing MyServer.main() starts a new Server thread, which creates a ServerSocket object on port 4444. The server socket accepts incoming connections on that port, creates an InputStreamReader object from the input stream coming from the client socket, then reads and prints the message sent by the client. A continuous while loop is used to await the connection and print the message received from the client.

MyClient.java:

public class MyClient {
    public static void main(String[] args) {
        new Thread(new Client()).start();
    }

    static class Client implements Runnable {
        @Override
        public void run() {
            Socket socket = null;

            try {
                socket = new Socket("localhost", 4444);

                PrintWriter outWriter = new PrintWriter(socket.getOutputStream(), true);
                outWriter.println("Hello");

                outWriter.close();
                socket.close();

                outWriter = new PrintWriter(socket.getOutputStream(), true);
                outWriter.println("Hello again");
            } catch (UnknownHostException uhe) {
                uhe.printStackTrace();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            } finally {
                try {
                    if (socket != null) {
                        socket.close();
                    }
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
    }
}

The MyClient.main() method above starts a Client thread, which creates a Socket instance and connects to the server host (localhost) and port (4444) defined earlier. A PrintWriter object is then created using the socket output stream to send a message to the server. This works fine and the message is printed by the server:

Message from client: Hello

The socket is then closed and another PrintWriter object is attempted to be created using the closed socket’s output stream. However, since the socket is closed, writing to it is not possible. Therefore, a SocketException is thrown:

java.net.SocketException: Socket is closed
    at java.net.Socket.getOutputStream(Socket.java:943)
    at MyClient$Client.run(MyClient.java:26)
    at java.lang.Thread.run(Thread.java:748)

 

How to Handle SocketException

Since SocketException is a checked exception, it can be handled by surrounding it with a try-catch block. The MyClient class in the earlier example can be updated to handle the exception:

public class MyClient {
    public static void main(String[] args) {
        new Thread(new Client()).start();
    }

    static class Client implements Runnable {
        @Override
        public void run() {
            Socket socket = null;

            try {
                socket = new Socket("localhost", 4444);

                PrintWriter outWriter = new PrintWriter(socket.getOutputStream(), true);
                outWriter.println("Hello");

                outWriter.close();
                socket.close();

                try {
                    outWriter = new PrintWriter(socket.getOutputStream(), true);
                } catch (SocketException se) {
                    if (socket.isClosed()) {
                        socket = new Socket("localhost", 4444);
                        outWriter = new PrintWriter(socket.getOutputStream(), true);
                    }
                }

                outWriter.println("Hello again");
            } catch (UnknownHostException uhe) {
                uhe.printStackTrace();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            } finally {
                try {
                    if (socket != null) {
                        socket.close();
                    }
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
    }
}

In the above example, the code that can throw the SocketException is surrounded in a try-catch block. In case a SocketException occurs when attempting to write to the socket, it is caught in the catch block and the socket instance is created and connected again to the server host and port. The PrintWriter object is also created again using the new socket output stream to send the second message to the server. This works successfully and both messages are now printed by the server:

Message from client: Hello
Message from client: Hello again

 

Track, Analyze and Manage Errors With Rollbar

Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Java errors easier than ever. Sign Up Today!

Related Resources

"Rollbar allows us to go from alerting to impact analysis and resolution in a matter of minutes. Without it we would be flying blind."

Error Monitoring

Start continuously improving your code today.

Get Started Shape