在Android中发送多部分或JSON数据时,出现Retrofit SocketTimeOutException。

8

在使用Retrofit库发送多部分或JSON数据时遇到了问题。

Retrofit接口:

@Multipart
@POST("/api/v1/protected/updateprofile")
void uploadPhoto(@Part("name") String name,
                 @Part("image") TypedFile file,
                 Callback<ApiResponseModel> callback);

适配器代码

private RestApi restApi;
RestAdapter restAdapter = new RestAdapter.Builder().setClient(new OkClient(getClient())).setConverter(new GsonConverter(gson)).setRequestInterceptor(interceptor).setLogLevel(RestAdapter.LogLevel.FULL).setEndpoint(Config.baseUrl).build();
        restApi = restAdapter.create(RestApi.class);

发送JSON请求后生成的错误日志

D/Retrofit﹕ ---- ERROR http://www.example.com/api/v1/protected/addfriends
11-05 11:22:18.594  13384-15325/com.veddislabs.plicx D/Retrofit﹕ java.io.InterruptedIOException: timeout
            at okio.AsyncTimeout.exit(AsyncTimeout.java:258)
            at okio.AsyncTimeout$2.read(AsyncTimeout.java:215)
            at okio.RealBufferedSource.indexOf(RealBufferedSource.java:206)
            at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:153)
            at com.squareup.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:189)
            at com.squareup.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:101)
            at com.squareup.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:676)
            at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:426)
            at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:371)
            at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:466)
            at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:73)
            at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:38)
            at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:321)
            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:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at retrofit.Platform$Android$2$1.run(Platform.java:142)
            at java.lang.Thread.run(Thread.java:856)
     Caused by: java.net.SocketException: Socket closed
            at libcore.io.Posix.recvfromBytes(Native Method)
            at libcore.io.Posix.recvfrom(Posix.java:136)
            at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:164)
            at libcore.io.IoBridge.recvfrom(IoBridge.java:513)
            at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
            at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
            at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:240)
            at okio.Okio$2.read(Okio.java:136)
            at okio.AsyncTimeout$2.read(AsyncTimeout.java:211)
            at okio.RealBufferedSource.indexOf(RealBufferedSource.java:206)
            at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:153)
            at com.squareup.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:189)
            at com.squareup.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:101)
            at com.squareup.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:676)
            at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:426)
            at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:371)
            at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:466)
            at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:73)
            at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:38)
            at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:321)
            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:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at retrofit.Platform$Android$2$1.run(Platform.java:142)
            at java.lang.Thread.run(Thread.java:856)

我已经尝试增加请求适配器中的超时时间

  private OkHttpClient getClient() {
        OkHttpClient client = new OkHttpClient();
        client.setConnectTimeout(30, TimeUnit.SECONDS);
        client.setReadTimeout(30, TimeUnit.SECONDS);
        return client;
    }

请查看下面的答案链接,它可能会对您有所帮助。https://dev59.com/Mabja4cB1Zd3GeqPkrYr#69376324 - Bharat Lalwani
2个回答

23

我几天前遇到了这个错误,发现你的解决方案是正确的,但需要更多时间。

private OkHttpClient getClient() {
    OkHttpClient client = new OkHttpClient();
    client.setConnectTimeout(5, TimeUnit.MINUTES);
    client.setReadTimeout(5, TimeUnit.MINUTES);
    return client;
}

针对OkHttp3

 private OkHttpClient getClient() {
    OkHttpClient client = new OkHttpClient.Builder()
    .connectTimeout(5, TimeUnit.MINUTES)
    .readTimeout(5, TimeUnit.MINUTES)
    .build();
    return client;
}

这就是为什么我发布了我尝试过的事情。 - Dharmendra Pratap Singh
2
这并不是一个解决方案!你必须实施一个请求重试机制而不是给它更多的时间... - Choletski
2
@Choletski 主要问题在于时间,因为请求并不总是失败,当用户的带宽非常低时,您不能限制用户上传非常小的文件大小。 - kroky

0

对我来说,问题是来自服务器端。

我不得不通过更改 API 服务器上的 sysctl 配置来禁用 tcp_timestamp。此外,如果您在同一台机器上有其他使用 TCP 的服务,例如 Redis 等,则应注意它们受到的影响。

从 Github 上的 issue 中找到了这个解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接