10
OkHttpClient client;

client = new OkHttpClient.Builder()
        .connectTimeout(5, TimeUnit.SECONDS)
        .writeTimeout(5, TimeUnit.SECONDS)
        .readTimeout(5, TimeUnit.SECONDS)
        .build();

Request request22 = new Request.Builder()
        .url("http://www.goo.com/")
        .build();

Utils.myLog("-begin-");
Response response = null;
try {
    response = client.newCall(request22).execute();
    if (response.isSuccessful()) {
        Utils.myLog("-donw-");
    }
} catch (Exception e) {
    e.printStackTrace();
    Utils.myLog("-error-" + e.toString());
}

This is my code, I have set timeout to 5 seconds, but it still taked 20 seconds to receive "error unknownhostexception " after "begin"? why my code is useless? I have looked the source code of OKHTTP, default timeout is 10 seconds(if I'm right), I'm confused.

Anyone can help, id really appreciated.

K Neeraj Lal
  • 6,768
  • 3
  • 24
  • 33
angryd
  • 326
  • 4
  • 8
  • 1
    An error message mentioning “unknown host” probably indicates DNS resolver issues: 20 seconds may refer to DNS timeout (DNS resolvers simply do not reply when they [still] have no answer) rather than TCP handshake timeout. I would start with finding out how does your software framework contact name servers and/or checking your particular network configuration. – Anton Samsonov Dec 25 '16 at 09:32
  • @AntonSamsonov thank you for answering! If there is no way to avoid DNS problem, How to set timeout no matter what exception? Thanks again! – angryd Dec 25 '16 at 09:49
  • For a regular GNU/Linux system, one can configure DNS attempts and timeouts in [/etc/resolv.conf](https://en.wikipedia.org/wiki/Resolv.conf), although I strongly recommend against that, as default DNS timings are a de-facto standard. However, on Android such configuration is unlikely to be available. Moreover, OkHttp may use its own Java-based resolver (I am familiar with neither OkHttp nor Java, just imagining all the possibilities), so you may need to influence that resolver rather than the system-provided service. – Anton Samsonov Dec 25 '16 at 10:00
  • @angryd please have to look at this [answer](https://stackoverflow.com/questions/55122236/okhttp3-never-timeout-on-slow-internet) its working fine for me. – Tanveer Munir Mar 15 '19 at 13:25

2 Answers2

4

For now, OkHttp can't interrupt time-consuming DNS requests (see https://github.com/square/okhttp/issues/95), but you still can do something like this:

        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .readTimeout(15, TimeUnit.SECONDS)
                .writeTimeout(15, TimeUnit.SECONDS)
                .connectTimeout(15, TimeUnit.SECONDS)
                .dns(hostname -> Single.fromCallable(
                        () -> Arrays.asList(InetAddress.getAllByName(hostname))
                ).timeout(15, TimeUnit.SECONDS)
                        .subscribeOn(Schedulers.io())
                        .observeOn(Schedulers.computation())
                        .onErrorReturnItem(new ArrayList<>())
                        .blockingGet())
                .build();
  • Thanks for this. Quick question, why observeOn(Schedulers.computation())? Do you think subscribeOn(Schedulers.trampoline()) with no observeOn might make sense? Or even no subscribeOn or observeOn whatsoever – Aleksander Niedziolko Apr 07 '21 at 14:55
  • The `observeOn` could be irrelevant. But the `subscribeOn` is very important. Without it, `timeout` would not work correctly. When not using a `subscribeOn`, when a `timeout` happens it will try to call `onError` on the subscriber, but instead of releasing the latch holding the `blockingGet`, it will get blocked because the upstream stuff is already running on the same thread. In those cases you get the worst of both worlds: the computation will take as long as the upstream operators take, but once they finished the timeout exception will be thrown and the result will be lost. – Cristian Aug 11 '23 at 19:28
0

Kotlin

class CustomDns : Dns {
        override fun lookup(hostname: String): List<InetAddress> {
            return Single.fromCallable {
                InetAddress.getAllByName(hostname)
            }.timeout(15, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.computation())
                .onErrorReturnItem(arrayOf())
                .blockingGet().toList()
        }
    }


OkHttpClient.Builder()
            .connectTimeout(15, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(15, TimeUnit.SECONDS)
            .dns(CustomDns())
            .build()
htafoya
  • 18,261
  • 11
  • 80
  • 104