java.net.SocketTimeoutException – How to Solve SocketTimeoutException
In this example we are going to talk about java.net.SocketTimeoutException
. This exception is a subclass of java.io.IOException
, so it is a checked exception.
From the javadoc we read that this exception :” Signals that a timeout has occurred on a socket read or accept”. That means that this exception emerges when a blocking operation of the two, an accept or a read, is blocked for a certain amount of time, called the timeout. Let’s say that the socket is configured with a timeout of 5 seconds.
If either the accept()
or read()
method, blocks for more than 5 seconds, a SocketTimeoutException
is thrown, designating that a timeout has occurred. It is important to note that after this exception is thrown. the socket remains valid, so you can retry the blocking call or do whatever you want with the valid socket.
1. A simple Cilent-Server application
To demonstrate this exception, I’m going to use the client-server application we’ve seen in java.net.ConnectException – How to solve Connect Exception. It creates two threads. The first one, SimpleServer
, opens a socket on the local machine on port 3333
. Then it waits for a connection to come in. When it finally receives a connection, it creates an input stream out of it, and simply reads one line of text from the client that was connected. The second thread, SimpleClient
, attempts to connect to the server socket that SimpleServer
opened. When it does so, it sends a line of text and that’s it.
SocketTimeoutExceptionExample.java:
package com.javacodegeeks.core.net.unknownhostexception; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; import java.net.UnknownHostException; public class SocketTimeoutExceptionExample { public static void main(String[] args) { new Thread(new SimpleServer()).start(); new Thread(new SimpleClient()).start(); } static class SimpleServer implements Runnable { @Override public void run() { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(3333); serverSocket.setSoTimeout(7000); while (true) { Socket clientSocket = serverSocket.accept(); BufferedReader inputReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); System.out.println("Client said :" + inputReader.readLine()); } } catch (SocketTimeoutException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (serverSocket != null) serverSocket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } static class SimpleClient implements Runnable { @Override public void run() { Socket socket = null; try { Thread.sleep(3000); socket = new Socket("localhost", 3333); PrintWriter outWriter = new PrintWriter( socket.getOutputStream(), true); outWriter.println("Hello Mr. Server!"); } catch (InterruptedException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (socket != null) socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
As you can see, because I’m launching the two threads simultaneously, I’ve put a 3 second delay in SimpleClient
for the client to wait before attempting to connect to the server socket, so as to give some time to server thread to open the server socket. Additionally, you will notice that in SimpleServer
I’ve specified the timeout to be of 7 seconds using this method : serverSocket.setSoTimeout(7000);
.
So, what we expect to happen here, is the communication to finish normally because the client will connect to the server after 3 seconds. That’s 4 seconds before the timeout barrier is reached. If you run the program, you will see this output
:
Client said :Hello Mr. Server!
That means that the client, successfully connected to the server and achieved to transmit its text. Now if you wait a bit more, you will see that a
1. An example of SocketTimeoutException
Now, if you keep the above program running, after the Client said :Hello Mr. Server!
message is transmitted successfully, you will notice that a SocketTimeoutException
is thrown:
Client said :Hello Mr. Server! java.net.SocketTimeoutException: Accept timed out at java.net.DualStackPlainSocketImpl.waitForNewConnection(Native Method) at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:135) at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398) at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:198) at java.net.ServerSocket.implAccept(ServerSocket.java:530) at java.net.ServerSocket.accept(ServerSocket.java:498) at com.javacodegeeks.core.net.unknownhostexception.SocketTimeoutExceptionExample$SimpleServer.run(SocketTimeoutExceptionExample.java:35) at java.lang.Thread.run(Thread.java:744)
That’s because, after the SimpleServer
serves the first client, it loops back to the accept()
method to serve the next client in line, but no one is connected. So, when the time out is reached, SocketTimeoutException
is thrown.
Of course, you can choose to handle this exception differently. For example , you can choose to loop back to the accept method, even if the exception is thrown, because the socket remains valid.
In the next example, I will launch two client threads with a certain delay between them, so that one of them sends its message before any exception occurs. The other client thread sends its message after an exception is thrown. Let’s see how you can do that, and pay attention to the server thread:
SocketTimeoutExceptionExample.java:
package com.javacodegeeks.core.net.unknownhostexception; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; import java.net.UnknownHostException; public class SocketTimeoutExceptionExample { public static void main(String[] args) throws InterruptedException { new Thread(new SimpleServer()).start(); new Thread(new SimpleClient()).start(); Thread.sleep(20000); new Thread(new SimpleClient()).start(); } static class SimpleServer implements Runnable { @Override public void run() { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(3333); serverSocket.setSoTimeout(7000); while (true) { try { Socket clientSocket = serverSocket.accept(); BufferedReader inputReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); System.out.println("Client said :"+ inputReader.readLine()); } catch (SocketTimeoutException e) { e.printStackTrace(); } } } catch (IOException e1) { e1.printStackTrace(); } finally { try { if (serverSocket != null) { serverSocket.close(); } } catch (IOException e) { e.printStackTrace(); } } } } static class SimpleClient implements Runnable { @Override public void run() { Socket socket = null; try { Thread.sleep(3000); socket = new Socket("localhost", 3333); PrintWriter outWriter = new PrintWriter( socket.getOutputStream(), true); outWriter.println("Hello Mr. Server!"); } catch (InterruptedException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (socket != null) socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
Now if you run the program for a while you will notice that every seven seconds a SocketTimeoutException
is thrown :
Client said :Hello Mr. Server! java.net.SocketTimeoutException: Accept timed out at java.net.DualStackPlainSocketImpl.waitForNewConnection(Native Method) at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:135) at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398) at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:198) at java.net.ServerSocket.implAccept(ServerSocket.java:530) at java.net.ServerSocket.accept(ServerSocket.java:498) at com.javacodegeeks.core.net.unknownhostexception.SocketTimeoutExceptionExample$SimpleServer.run(SocketTimeoutExceptionExample.java:38) at java.lang.Thread.run(Thread.java:744) java.net.SocketTimeoutException: Accept timed out at java.net.DualStackPlainSocketImpl.waitForNewConnection(Native Method) at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:135) at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398) at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:198) at java.net.ServerSocket.implAccept(ServerSocket.java:530) at java.net.ServerSocket.accept(ServerSocket.java:498) at com.javacodegeeks.core.net.unknownhostexception.SocketTimeoutExceptionExample$SimpleServer.run(SocketTimeoutExceptionExample.java:38) at java.lang.Thread.run(Thread.java:744) Client said :Hello Mr. Server! java.net.SocketTimeoutException: Accept timed out at java.net.DualStackPlainSocketImpl.waitForNewConnection(Native Method) at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:135) at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398) at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:198) at java.net.ServerSocket.implAccept(ServerSocket.java:530) at java.net.ServerSocket.accept(ServerSocket.java:498) at com.javacodegeeks.core.net.unknownhostexception.SocketTimeoutExceptionExample$SimpleServer.run(SocketTimeoutExceptionExample.java:38) at java.lang.Thread.run(Thread.java:744) ... ... ...
So as you can see even after the exception is thrown, the socket remains active and receives a message form the second client thread. The above program will keep throwing a SocketTimeoutException
every seven seconds.
3. How to Solve SocketTimeoutException
In the above example we’ve shown what causes a SocketTimeoutException
in the case of the accept()
. The same principles will apply in the case of read()
. Now, what can you do to avoid that exception. If the server side application is under your control, you should try yo adjust the timeout barrier so that its more flexible on network delays. You should surely consider doing that especially when your server application will run in a remote machine. Other than that, you can check whatever causes delays in your network, a malfunctioning router etc.
Download Source Code
This was an example on java.net.SocketTimeoutException
and how to solve SocketTimeoutException
. You can download the source code of this example here : SocketTimeoutExceptionExample.zip