【问题标题】:java.net.SocketTimeoutException: timeoutjava.net.SocketTimeoutException:超时
【发布时间】:2016-07-27 02:57:33
【问题描述】:

使用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

【问题讨论】:

  • 为您的客户提供更大的读取超时值。似乎从套接字读取流时发生超时。
  • @NikolaDespotoski 我已经将 Socket 超时设置为 15 分钟我仍然面临这个问题

标签: java android httpurlconnection okhttp3


【解决方案1】:

追赶追赶

runCatching {
       service
}
 .map {
       if (it.isSuccessful && it.body() != null) {
           Success(Unit)
       } else {
           Error(Failure.AuthError.error(it.errorBody()))
       }
}
 .getOrElse {
       Error(Failure.Throwable(it))
}

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 如果服务器宕机了怎么办?然后它的行为就像错误的 URL 一样,因为响应不会来自服务器。所以设置正确的 URL 不是解决方案。
    【解决方案3】:
    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()
            }
    

    【讨论】:

      【解决方案4】:

      您需要了解,仅添加此内容并不能解决您的问题:

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

      如果您使用 Kotlin + Retrofit + Coroutines,那么只需使用 trycatch 进行网络操作,例如,

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

      其中,Exception 是 kotlin 的类型,而不是 java.lang 的类型

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

      1. HttpException
      2. SocketTimeoutException
      3. 致命异常:DefaultDispatcher 等

      这是我的usersList() 函数

      @GET(AppConstants.APIEndPoints.HOME_CONTENT)
      suspend fun usersList(): UserListResponseModel
      

      【讨论】:

        【解决方案5】:

        在 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()
        

        【讨论】:

          【解决方案6】:

          这解决了我的问题:

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

          【讨论】:

          • 这与其他人的评论有何不同?
          • 没有像前两个(setConnectTimeout 和 setReadTimeout)那样的设置器,我认为我的设置器更有条理:) 此外,没有一个被标记为已解决;)
          • 拯救了我的一天。我正要在网上胡闹
          • 我认为它是迄今为止最漂亮的解决方案
          【解决方案7】:

          我解决了增加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();
          

          【讨论】:

          • 设置也writeTimeout解决了这个问题,谢谢:)
          • 如果我们要上传文件,我们必须如上所述更改默认的writeTimeout。
          【解决方案8】:

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

          OkHttpClient client = new OkHttpClient();
          client.setConnectTimeout(30, TimeUnit.SECONDS); // connect timeout
          client.setReadTimeout(30, TimeUnit.SECONDS);    // socket timeout
          

          【讨论】:

          • 我已经将连接超时值设置为 30 秒,将套接字超时值设置为 15 分钟。我仍然面临同样的问题,应用程序在 10 秒内超出异常
          • @DBragion 根据 Square github.com/square/okhttp/wiki/Recipes 提供的文档。如果请求大小超过 1MiB,建议不要使用此 post string 方法。您可以回退到 HttpUrlConnection 方法,或者您需要实现文档中描述的后流。
          • @Vivek -- 你找到解决方案了吗?我正在经历类似的事情。
          • 没有实现post流或使用httpurlconnection
          • 我已经设置为 5 分钟我仍然遇到这个问题
          猜你喜欢
          • 1970-01-01
          • 2011-01-29
          • 1970-01-01
          • 2011-07-13
          • 2013-12-01
          • 2015-10-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多