Why do I get java.net.SocketTimeoutException with OkHttp?

You are most likely affected by the socket timeouts imposed by the operating system. Java can't extend them since the sockets are managed by the system. As per this great answer, "Changing TCP Timeouts" section:

Unfortunately since TCP connections are managed on the OS level, Java does not support configuring timeouts on a per-socket level such as in java.net.Socket. I have found some attempts to use Java Native Interface (JNI) to create Java sockets that call native code to configure these options, but none appear to have widespread community adoption or support.

For MacOS you have to look at sysctl net.inet.tcp output and see what are the system limits.


I think the issue is somewhere else. The timeout does work. I tried the following on my machine and it worked for 30 seconds

package test;

import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 *
 * @author jingged
 */
public class Test {
OkHttpClient httpClient = null;
     void initClient(){
        httpClient = new OkHttpClient.Builder()
        .connectTimeout(30, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS)
        .build();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Test test = new Test();
        test.initClient();
        for(int i = 0;i<10;i++){
            new Thread(new Runnable(){
                @Override
                public void run() {
                   Request request = new Request.Builder().url("https://10.255.255.1").build();
                   Instant start = Instant.now();
                   try (Response response = test.httpClient.newCall(request).execute()) {
                        String s =  response.body().string();
                        System.out.println(s);
                    } catch (IOException ex) {
                        if (ex instanceof java.net.SocketTimeoutException){
                            System.err.print("Socket TimeOut");
                        }else{
                            ex.printStackTrace();
                        }
                    }
                   Instant end = Instant.now();
                    Duration interval = Duration.between(start, end);
                    System.out.println("Execution time " + interval.getSeconds()+" seconds");
                }

            }).start();
        }
    }
}

Output:

Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Execution time 30 seconds
Socket TimeOutSocket TimeOutSocket TimeOutSocket TimeOutSocket TimeOutSocket TimeOutSocket TimeOutSocket TimeOutSocket TimeOutSocket TimeOut
BUILD SUCCESSFUL (total time: 32 seconds)

Try the above code. the url mentioned in the above code will produce TimeOut exception as it doesn't exists but the timeout time should keep it going for 30 seconds. BTW I tested this on MAC OS High Sierra with Java 8 and netbeans 8.2 with okhttp3

Tags:

Java

Http

Okhttp3