Elyakim Levi Elyakim Levi - 2 months ago 28
Java Question

Unable to catch SocketTimeoutException thrown from socket.connect(InetAddress, timeout)

I'm developing an app that connects to a server via socket connection to read and write data.
I'm using runInBackground() method in AsyncTask to do this.

I use my PC as a server and connect my android device to the WiFi to connect to the PC.

I want to simulate a case where the server is unavailable so I disconnect my device from the WiFi and run the code.

I use the following code:

try
{
socket = new Socket();
socket.connect(new InetSocketAddress("192.168.1.104", 4444), 10000);
...
...
}
catch (SocketTimeoutException e)
{
e.printStackTrace();
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}


A SocketTimeoutException is thrown after 10 seconds as expected but the problem is that none of the catch blocks actually catch the exception. How is that possible?

Here's the log:

11-09 17:57:15.286: W/System.err(12050): java.net.SocketTimeoutException: failed to connect to /192.168.1.104 (port 4444) after 10000ms
11-09 17:57:15.301: W/System.err(12050): at libcore.io.IoBridge.connectErrno(IoBridge.java:159)
11-09 17:57:15.301: W/System.err(12050): at libcore.io.IoBridge.connect(IoBridge.java:112)
11-09 17:57:15.301: W/System.err(12050): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
11-09 17:57:15.301: W/System.err(12050): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
11-09 17:57:15.306: W/System.err(12050): at java.net.Socket.connect(Socket.java:842)
11-09 17:57:15.306: W/System.err(12050): at com.elyakimsportal.communication.ContactServer$RetrieveProfilesTask.doInBackground(ContactServer.java:183)
11-09 17:57:15.306: W/System.err(12050): at com.elyakimsportal.communication.ContactServer$RetrieveProfilesTask.doInBackground(ContactServer.java:1)
11-09 17:57:15.311: W/System.err(12050): at android.os.AsyncTask$2.call(AsyncTask.java:287)
11-09 17:57:15.311: W/System.err(12050): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
11-09 17:57:15.311: W/System.err(12050): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
11-09 17:57:15.311: W/System.err(12050): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
11-09 17:57:15.316: W/System.err(12050): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
11-09 17:57:15.316: W/System.err(12050): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
11-09 17:57:15.316: W/System.err(12050): at java.lang.Thread.run(Thread.java:856)
11-09 17:57:15.316: I/System.out(12050): closed connection to server


Also, I looked at the documentation of the Socket.connect(InetSocketAddress, timeout) method and it doesn't say it ever throws SocketTimeoutException so that makes it even more confusing.

Parameters
remoteAddr the address and port of the remote host to connect to.
timeout the timeout value in milliseconds or 0 for an infinite timeout.

Throws
IllegalArgumentException if the given SocketAddress is invalid or not supported or the timeout value is negative.
IOException if the socket is already connected or an error occurs while connecting.


By the way, my app doesn't crash. Am I right to assume that that's because it's in a different thread?

Answer

It looks to me that in the example code you provided the SocketTimeoutException is being caught. This would make sense since you said your app doesn't crash.

It might still 'look' like it's crashing or not catching the exception because you are printing the stack track to the terminal using e.printStackTrace().

If you don't want to fill the log with these exceptions, consider the rewrite:

try {
    socket = new Socket();
    socket.connect(new InetSocketAddress("192.168.1.104", 4444), 10000);
    ...
    ...

} catch (SocketTimeoutException e) {
    System.err.println("SocketTimeoutException: " + e.getMessage());

} catch (ClassNotFoundException e) {
    System.err.println("ClassNotFoundException: " + e.getMessage());

} catch (IOException e) {
    System.err.println("IOException: " + e.getMessage());

} catch (Exception e) {
    System.err.println("Exception: " + e.getMessage());

}