OkHttp3 SocketTimeoutException (in Android app) -- 如何设置异步请求的读取超时时间?
OkHttp3 SocketTimeoutException (in Android app) -- How to set read timeout for asynchronous request?
我在尝试 OkHttp3 异步获取时不断收到 java.net.SocketTimeoutException。这表明我没有将读取超时值设置得足够高(我认为默认值为 10 秒)。
更大的问题是 "How to prevent this exception?" 但是,除非有人有更好的初始策略,否则我的直接问题是 "How to set a read timeout value for the request?"
在我的代码中,我使用了来自 Okttp 食谱页面的信息 here
注意我的 try-catch 的前两行被注释掉了。那是因为我无法使用我需要的那种构建器(能够设置超时值,OkHttpClient.Builder)来添加 header 信息 (Request.Builder) .
我的代码如下所示:
m_client = new OkHttpClient();
try
{
//OkHttpClient.Builder bldr = m_client.newBuilder();
//bldr.readTimeout(0, TimeUnit.SECONDS);
Request.Builder reqBuilder = new Request.Builder();
reqBuilder.addHeader("authorization", getToken());
Request request = reqBuilder.url("http://plusdev.kooklah.com/api/v2_1/items/get").build();
m_client.newCall(request).enqueue(new Callback()
{
@Override
public void onFailure(Call call, IOException e)
{
Log.i("Logit", "Inside onFailure() -- IOException: " + e.getMessage() + " ----- stack trace: " + UtilGen.exceptionToString(e));
runOnUiThread(new Runnable()
{
@Override
public void run()
{
// do stuff on UI thread
}
});
}
@Override
public void onResponse(Call call, final Response responseIn)
{
try
{
m_sServerResponse = responseIn.body().string();
}
catch (Exception ex)
{
Log.i("LogIt", " ---Inside onResponse() -- Exception occurred. ex: " + ex.toString());
}
runOnUiThread(new Runnable()
{
@Override
public void run()
{
Log.i("LogIt", " ---Inside onResponse() -- inside run().");
if (!m_sServerResponse.isEmpty())
{
Log.i("LogIt", " ---Inside onResponse() -- inside run() -- Success");
processDownloadedAssessments(m_sServerResponse);
}
}
});
}
});
}
catch (Exception ex)
{
Log.i("LogIt", "ex: " + ex.getMessage());
}
我在 okhttp github 站点上发现了一个似乎直接相关的已报告问题 here。甚至还有一个设置读取超时的建议,如上所述,它已被注释掉,因为我不知道如何让那种构建器承担 Recipe 页面上描述的异步请求。
我的异常的堆栈跟踪如下,但请注意,大多数时候我没有得到异常。堆栈跟踪:
01-19 14:04:52.192: I/LogIt(25650): Inside onFailure() -- IOException: null ----- stack trace: java.net.SocketTimeoutException
01-19 14:04:52.192: I/LogIt(25650): at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
01-19 14:04:52.192: I/LogIt(25650): at java.net.PlainSocketImpl.access[=12=]0(PlainSocketImpl.java:37)
01-19 14:04:52.192: I/LogIt(25650): at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
01-19 14:04:52.192: I/LogIt(25650): at okio.Okio.read(Okio.java:138)
01-19 14:04:52.192: I/LogIt(25650): at okio.AsyncTimeout.read(AsyncTimeout.java:236)
01-19 14:04:52.192: I/LogIt(25650): at okio.RealBufferedSource.indexOf(RealBufferedSource.java:325)
01-19 14:04:52.192: I/LogIt(25650): at okio.RealBufferedSource.indexOf(RealBufferedSource.java:314)
01-19 14:04:52.192: I/LogIt(25650): at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:210)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http1.Http1Codec.readResponse(Http1Codec.java:191)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:132)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:54)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:179)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.RealCall$AsyncCall.execute(RealCall.java:129)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
01-19 14:04:52.192: I/LogIt(25650): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
01-19 14:04:52.192: I/LogIt(25650): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
01-19 14:04:52.192: I/LogIt(25650): at java.lang.Thread.run(Thread.java:818)
而不是
m_client = new OkHttpClient();
您应该使用如下构建器创建客户端:
m_client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
当您像这样创建客户端时,每个 Request
执行此客户端(使用 m_client.newCall(...)
)将使用构建器中指定的超时。
我在尝试 OkHttp3 异步获取时不断收到 java.net.SocketTimeoutException。这表明我没有将读取超时值设置得足够高(我认为默认值为 10 秒)。
更大的问题是 "How to prevent this exception?" 但是,除非有人有更好的初始策略,否则我的直接问题是 "How to set a read timeout value for the request?"
在我的代码中,我使用了来自 Okttp 食谱页面的信息 here
注意我的 try-catch 的前两行被注释掉了。那是因为我无法使用我需要的那种构建器(能够设置超时值,OkHttpClient.Builder)来添加 header 信息 (Request.Builder) .
我的代码如下所示:
m_client = new OkHttpClient();
try
{
//OkHttpClient.Builder bldr = m_client.newBuilder();
//bldr.readTimeout(0, TimeUnit.SECONDS);
Request.Builder reqBuilder = new Request.Builder();
reqBuilder.addHeader("authorization", getToken());
Request request = reqBuilder.url("http://plusdev.kooklah.com/api/v2_1/items/get").build();
m_client.newCall(request).enqueue(new Callback()
{
@Override
public void onFailure(Call call, IOException e)
{
Log.i("Logit", "Inside onFailure() -- IOException: " + e.getMessage() + " ----- stack trace: " + UtilGen.exceptionToString(e));
runOnUiThread(new Runnable()
{
@Override
public void run()
{
// do stuff on UI thread
}
});
}
@Override
public void onResponse(Call call, final Response responseIn)
{
try
{
m_sServerResponse = responseIn.body().string();
}
catch (Exception ex)
{
Log.i("LogIt", " ---Inside onResponse() -- Exception occurred. ex: " + ex.toString());
}
runOnUiThread(new Runnable()
{
@Override
public void run()
{
Log.i("LogIt", " ---Inside onResponse() -- inside run().");
if (!m_sServerResponse.isEmpty())
{
Log.i("LogIt", " ---Inside onResponse() -- inside run() -- Success");
processDownloadedAssessments(m_sServerResponse);
}
}
});
}
});
}
catch (Exception ex)
{
Log.i("LogIt", "ex: " + ex.getMessage());
}
我在 okhttp github 站点上发现了一个似乎直接相关的已报告问题 here。甚至还有一个设置读取超时的建议,如上所述,它已被注释掉,因为我不知道如何让那种构建器承担 Recipe 页面上描述的异步请求。
我的异常的堆栈跟踪如下,但请注意,大多数时候我没有得到异常。堆栈跟踪:
01-19 14:04:52.192: I/LogIt(25650): Inside onFailure() -- IOException: null ----- stack trace: java.net.SocketTimeoutException
01-19 14:04:52.192: I/LogIt(25650): at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
01-19 14:04:52.192: I/LogIt(25650): at java.net.PlainSocketImpl.access[=12=]0(PlainSocketImpl.java:37)
01-19 14:04:52.192: I/LogIt(25650): at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
01-19 14:04:52.192: I/LogIt(25650): at okio.Okio.read(Okio.java:138)
01-19 14:04:52.192: I/LogIt(25650): at okio.AsyncTimeout.read(AsyncTimeout.java:236)
01-19 14:04:52.192: I/LogIt(25650): at okio.RealBufferedSource.indexOf(RealBufferedSource.java:325)
01-19 14:04:52.192: I/LogIt(25650): at okio.RealBufferedSource.indexOf(RealBufferedSource.java:314)
01-19 14:04:52.192: I/LogIt(25650): at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:210)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http1.Http1Codec.readResponse(Http1Codec.java:191)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:132)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:54)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:179)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.RealCall$AsyncCall.execute(RealCall.java:129)
01-19 14:04:52.192: I/LogIt(25650): at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
01-19 14:04:52.192: I/LogIt(25650): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
01-19 14:04:52.192: I/LogIt(25650): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
01-19 14:04:52.192: I/LogIt(25650): at java.lang.Thread.run(Thread.java:818)
而不是
m_client = new OkHttpClient();
您应该使用如下构建器创建客户端:
m_client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
当您像这样创建客户端时,每个 Request
执行此客户端(使用 m_client.newCall(...)
)将使用构建器中指定的超时。