Retrofit中的SocketTimeoutException

时间:2016-08-30 05:05:07

标签: android retrofit okhttp socket-timeout-exception

我正在尝试向服务器 POST 请求提取数据但有时会发生SocketTimeoutException

我使用Ok3Client来解决它,但我遇到了同样的异常我该怎样解决它?

我的代码在

下面
public void getNormalLogin() {
        if (mProgressDialog == null) {
            mProgressDialog = ViewUtils.createProgressDialog(mActivity);
            mProgressDialog.show();
        } else {
            mProgressDialog.show();
        }

        if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13) {
            restadapter = new RestAdapter.Builder().setEndpoint(HOST).setLogLevel(RestAdapter.LogLevel.FULL).setClient(new Ok3Client(new OkHttpClient())).build();
            mApi = restadapter.create(Api.class);
            mApi.SignIn(etEmail.getText().toString(), etPassword.getText().toString(), new Callback<ArrayList<SignUpMainBean>>() {
                @Override
                public void success(ArrayList<SignUpMainBean> signUpMainBeen, Response response) {
                    mProgressDialog.dismiss();
                    LOGD("Status:: ::", String.valueOf(response.getStatus()));
                    LOGD("Code:: ::", String.valueOf(signUpMainBeen.get(0).getCode()));
                    if (signUpMainBeen != null && signUpMainBeen.size() > 0) {
                        if (signUpMainBeen.get(0).getCode() == 1) {

                            for (int i = 0; i < signUpMainBeen.size(); i++) {
                                for (int j = 0; j < signUpMainBeen.get(i).getResult().size(); j++) {
                                    showToast(mActivity, getString(R.string.you_have_successfully_login), Toast.LENGTH_SHORT);
                                    LOGD("Success", "Success");                                                                         
                                   finish();
                                    SignIn.mActivity.finish();
                                }
                            }

                        } else if (signUpMainBeen.get(0).getCode() == 0) {
                            mProgressDialog.dismiss();
                            showToast(mActivity, getString(R.string.invalid_email_password), Toast.LENGTH_SHORT);
                            LOGD("Invalid email or password", "Invalid email or password");
                        } else if (signUpMainBeen.get(0).getCode() == -1) {
                            mProgressDialog.dismiss();
                            showToast(mActivity, getString(R.string.your_account_is_inactive), Toast.LENGTH_SHORT);
                            LOGD("Your account is inactive", "Your account is inactive");
                        }
                    }
                }

                @Override
                public void failure(RetrofitError error) {
                    mProgressDialog.dismiss();
                    showToast(mActivity, getString(R.string.can_not_connect_to_server), Toast.LENGTH_SHORT);
                    LOGD("Failure", "Failure");
                }
            });
        }
    }

我的错误日志是

D/Retrofit: java.net.SocketTimeoutException
at java.net.PlainSocketImpl.read(PlainSocketImpl.java:532)
at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:40)
at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:255)
at okio.Okio$2.read(Okio.java:139)
at okio.AsyncTimeout$2.read(AsyncTimeout.java:211)
at okio.RealBufferedSource.indexOf(RealBufferedSource.java:306)
at okio.RealBufferedSource.indexOf(RealBufferedSource.java:300)
at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:196)
at okhttp3.internal.http.Http1xStream.readResponse(Http1xStream.java:185)
at okhttp3.internal.http.Http1xStream.readResponseHeaders(Http1xStream.java:126)
at okhttp3.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:723)
at okhttp3.internal.http.HttpEngine.access$200(HttpEngine.java:81)
at okhttp3.internal.http.HttpEngine$NetworkInterceptorChain.proceed(HttpEngine.java:708)
at okhttp3.internal.http.HttpEngine.readResponse(HttpEngine.java:563)
at okhttp3.RealCall.getResponse(RealCall.java:241)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:198)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:160)
at okhttp3.RealCall.execute(RealCall.java:57)
at com.jakewharton.retrofit.Ok3Client.execute(Ok3Client.java:40)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:326)
at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220)
at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278)
at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at retrofit.Platform$Android$2$1.run(Platform.java:142)
at java.lang.Thread.run(Thread.java:818)

5 个答案:

答案 0 :(得分:52)

如果提取花费更多时间,请增加时间,使用它为我工作的代码

 OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(100, TimeUnit.SECONDS)
            .readTimeout(100,TimeUnit.SECONDS).build();
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("yourbaseurl").client(client)
            .addConverterFactory(GsonConverterFactory.create(new  Gson())).build();

干草这不是最好的做法 后端不应该花这么长时间,并且必须通知用户错误或再次尝试消息

答案 1 :(得分:27)

防止SocketTimeoutException超出了我们的限制......有效处理它的一种方法是定义connection timeout

的示例
  

改造1.9.0

restadapter = new RestAdapter.Builder().setEndpoint(HOST).setLogLevel(RestAdapter.LogLevel.FULL).setClient(new OkHttpClient()
                .setReadTimeout(30, TimeUnit.SECONDS)
                .setConnectTimeout(30, TimeUnit.SECONDS)).build();
  

改造2.0.0

OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(10, TimeUnit.SECONDS);
client.setReadTimeout(30, TimeUnit.SECONDS);
retrofit = new Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .client(client)
        .build();
  

改造2.4.0

// setting custom timeouts
    OkHttpClient.Builder client = new Builder();
    client.connectTimeout(15, TimeUnit.SECONDS);
    client.readTimeout(15, TimeUnit.SECONDS);
    client.writeTimeout(15, TimeUnit.SECONDS);

    if (retrofit == null) {
      retrofit = new Retrofit.Builder()
          .baseUrl(BASE_URL)
          .addConverterFactory(GsonConverterFactory.create())
          .client(client.build())
          .build();
    }
    return retrofit;
  }

答案 2 :(得分:0)

可能的解决方法是确保将正确的请求正文发送到服务器。例如,服务器在其请求正文中是否需要x-www-form-urlencodedform-data?一种测试方法的简单方法是使用Postman

答案 3 :(得分:0)

对我来说,捕捉并抛出一个新的IOException很有用

@Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Response response = null;
        try {
            response = chain.proceed(request);
        }catch (SocketTimeoutException e){
            throw new IOException();
        }
        String url = request.url().url().toString();
        if (existInWhiteList(url)) {
            return response;
        }
        return logResponse(response);
    }

,您可以在此new IOException()中添加自己的信息;

答案 4 :(得分:0)

我也遇到一些要求。通常在有活动请求且由于与网络断开连接而得到SocketTimeoutException时得到此消息。之后,相同的请求总是抛出SocketTimeoutException

我按照“ java.net.SocketTimeoutException from HTTP/2 connection leaves dead okhttp clients in pool”中的建议使用以下代码构建了OkHttpClient

val builder = OkHttpClient.Builder()
    .cache(cache)
    .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
    .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
    .connectionPool(ConnectionPool(0, 5, TimeUnit.MINUTES))
    .protocols(listOf(Protocol.HTTP_1_1))

设置connectionPoolprotocols将解决SocketTimeoutException由超时引起的问题。

这是一个临时修复程序,希望在OkHttp使用的Retrofit的未来版本中得到解决。