57

使用OkHttp库,应用程序面临以下SocketTimeoutException问题。如果请求大小更小,那么它工作正常(小于 1MB)。我在 10 秒内得到了这个异常,即使我的套接字超时(readTimeout)值要高得多。请求始终失败(大小为 1.8MB)。当我使用它执行请求时,HttpUrlConnection它工作正常。失败的可能原因是什么?

   03-29 12:16:38.997 32066-4018/com.mobile W/System.err: java.net.SocketTimeoutException: timeout
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.Okio$3.newTimeoutException(Okio.java:207)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.AsyncTimeout.exit(AsyncTimeout.java:261)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.AsyncTimeout$1.write(AsyncTimeout.java:158)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:176)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.RealBufferedSink.write(RealBufferedSink.java:46)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okhttp3.internal.http.Http1xStream$FixedLengthSink.write(Http1xStream.java:286)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:176)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okio.RealBufferedSink.write(RealBufferedSink.java:96)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okhttp3.RequestBody$2.writeTo(RequestBody.java:96)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okhttp3.internal.http.HttpEngine$NetworkInterceptorChain.proceed(HttpEngine.java:704)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okhttp3.internal.http.HttpEngine.readResponse(HttpEngine.java:563)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okhttp3.RealCall.getResponse(RealCall.java:241)
    03-29 12:16:38.997 32066-4018/com.mobile W/System.err:     at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:198)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:160)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at okhttp3.RealCall.execute(RealCall.java:57)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at com.mobizio.api.BaseApi.sendOkHttpRequest(BaseApi.java:81)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at com.mobizio.api.BaseApi.doInBackground(BaseApi.java:45)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at com.mobizio.api.BaseApi.doInBackground(BaseApi.java:30)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:292)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at java.lang.Thread.run(Thread.java:818)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err: Caused by: java.net.SocketException: socket is closed
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl$SSLOutputStream.write(OpenSSLSocketImpl.java:759)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at okio.Okio$1.write(Okio.java:80)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:     at okio.AsyncTimeout$1.write(AsyncTimeout.java:155)
    03-29 12:16:38.998 32066-4018/com.mobile W/System.err:  ... 20 more
4

9 回答 9

61

对于 OkHttp 3,OkHttp 的默认值为 10 秒。您可以将超时时间增加到 30 秒。

OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(30, TimeUnit.SECONDS); // connect timeout
client.setReadTimeout(30, TimeUnit.SECONDS);    // socket timeout
于 2016-04-06T16:30:05.633 回答
52

我解决了这个问题writeTimeout()

尝试:

OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(5, TimeUnit.MINUTES) // connect timeout
.writeTimeout(5, TimeUnit.MINUTES) // write timeout
.readTimeout(5, TimeUnit.MINUTES); // read timeout

okHttpClient = builder.build();
于 2016-10-11T11:36:19.237 回答
18

这解决了我的问题:

OkHttpClient innerClient = new OkHttpClient.Builder()
            .connectTimeout(5, TimeUnit.MINUTES) // connect timeout
            .writeTimeout(5, TimeUnit.MINUTES) // write timeout
            .readTimeout(5, TimeUnit.MINUTES) // read timeout
            .build();
于 2019-07-03T14:11:54.867 回答
6

将此用于 Kotlin

 val client1 = OkHttpClient.Builder()
                .connectTimeout(2, TimeUnit.MINUTES)
                .writeTimeout(2, TimeUnit.MINUTES) // write timeout
                .readTimeout(2, TimeUnit.MINUTES) // read timeout
                .addInterceptor(
                    BasicAuthInterceptor(
                        AmvaccAppConstants.AUTHENTICATE_USER_NAME, AmvaccAppConstants.AUTHENTICATE_USER_PASSWORD
                    )
                )
                .addInterceptor(interceptor)
                .build()
于 2019-07-12T12:31:19.127 回答
5

您需要了解仅添加它不会解决您的问题:

OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)

如果您使用的是Kotlin + Retrofit + Coroutines,那么只需将tryandcatch用于网络操作,例如,

viewModelScope.launch(Dispatchers.IO) {
        try {
            val userListResponseModel = apiEndPointsInterface.usersList()
            returnusersList(userListResponseModel)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

其中,异常是类型kotlin而不是java.lang

这将处理每个异常,例如,

  1. 异常
  2. 套接字超时异常
  3. 致命异常:DefaultDispatcher 等

这是我的usersList()功能

@GET(AppConstants.APIEndPoints.HOME_CONTENT)
suspend fun usersList(): UserListResponseModel
于 2020-06-08T15:56:43.950 回答
0
If you are using Retrofit and Kotlin then use following code:
    var BASE_URL:String="Your URL"
    val clientSetup = OkHttpClient.Builder()
        .connectTimeout(1, TimeUnit.MINUTES)
        .writeTimeout(1, TimeUnit.MINUTES) // write timeout
        .readTimeout(1, TimeUnit.MINUTES) // read timeout
        .build()

    val getClientApi: ApiInterface
        get() {
            var retrofit: Retrofit =  Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .client(clientSetup)
                .build()
        }
于 2020-10-05T12:19:23.467 回答
0

在我的情况下,将ping 间隔添加到 OkHttp 有助于减少应用程序中的SocketTimeoutExceptions数量。

OkHttpClient.Builder()
        .pingInterval(3, SECONDS)
        .build()

但我不确定这些超时是否与请求大小有关。我在 github 上的这个 issue 中也提到了它,报告给 OkHttp 库

于 2022-01-11T13:02:54.760 回答
0

跑进追赶

runCatching {
       service
}
 .map {
       if (it.isSuccessful && it.body() != null) {
           Success(Unit)
       } else {
           Error(Failure.AuthError.error(it.errorBody()))
       }
}
 .getOrElse {
       Error(Failure.Throwable(it))
}
于 2021-10-15T10:21:43.767 回答
-1

检查您的网址是否正确。此错误可能是由于错误的 url 行

于 2021-04-10T09:58:21.023 回答