Jac*_*rta 4 android timeout httpclient httprequest
我在Android上遇到了DefaultHttpClient的超时问题.我正在尝试使用以下代码设置超时:
HttpClient client = new DefaultHttpClient();
HttpParams httpParameters = client.getParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 4000);
HttpConnectionParams.setSoTimeout(httpParameters, 4000);
Run Code Online (Sandbox Code Playgroud)
但是,如果设备连接到没有Internet连接的网络,则永远不会触发超时,并且http请求的执行永远不会引发任何超时异常.我正在执行http请求如下:
HttpResponse httpResponse = client.execute(request);
Run Code Online (Sandbox Code Playgroud)
我也试过在HttpRequest上设置超时,使用以下行:
HttpRequestBase request = ...
request.setParams(httpParameters);
Run Code Online (Sandbox Code Playgroud)
Android似乎忽略了超时设置,并且在没有互联网连接的网络上执行http请求时,所有请求在大约20秒后失败,而不是在我的超时设置之后.
我还试图关闭所有的互联网连接,并在使用并行线程超时后中止http请求.我使用了以下代码:
HttpClient client = new DefaultHttpClient();
HttpParams httpParameters = client.getParams();
HttpRequestBase request = ...
request.setParams(httpParameters);
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutReal);
HttpConnectionParams.setSoTimeout(httpParameters, timeoutReal);
request.setParams(httpParameters);
((DefaultHttpClient) client).setParams(httpParameters);
Thread t = new Thread(){
public void run()
{
try
{
Thread.sleep(4000);
request.abort();
client.getConnectionManager().closeExpiredConnections();
client.getConnectionManager().closeIdleConnections(4000,TimeUnit.MILLISECONDS);
client.getConnectionManager().shutdown();
Log.i("TEST SHUTDOWN","SHUT DOWN ALL CONNECTIONS");
}
catch (InterruptedException e)
{
}
}
};
try
{
t.start();
HttpResponse httpResponse = client.execute(request);
}
catch (Exception e)
{
Log.i("TEST SHUTDOWN","EXCEPTION "+e);
}
finally
{
t.interrupt();
}
Run Code Online (Sandbox Code Playgroud)
但即使我从日志中看到请求被中止且连接管理器关闭,请求的执行也不会中断/中止,并且在超时设置时不会引发异常.请求始终在20秒后结束.
知道为什么吗?
您可能看到的是DNS查找超时.当您的HTTP客户端尝试建立连接时,它首先要尝试将您的URL的主机名解析为IP地址.执行此操作时,不会考虑您的超时设置(这些超时值仅在尝试实际建立套接字连接时使用).如果您没有良好的Internet连接,您的DNS查找将停止,直到超时.一旦发生这种情况,您的HTTP请求应立即失败UnknownHostException.
遗憾的是,您无法控制DNS超时,因此解决问题的唯一方法是首先确定您的DNS解析是否正常.您应该在一个单独的线程中执行此操作,如果您在几秒钟内未获得成功的主机解析,则您知道您的Internet连接不可靠,您甚至不必尝试HTTP请求.
所以你可以尝试这样的事情:
HttpClient client = new DefaultHttpClient();
HttpParams httpParameters = client.getParams();
HttpRequestBase request = ...
request.setParams(httpParameters);
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutReal);
HttpConnectionParams.setSoTimeout(httpParameters, timeoutReal);
request.setParams(httpParameters);
((DefaultHttpClient) client).setParams(httpParameters);
// The thread that is waiting to execute the HTTP request
final Thread waitingThread = Thread.currentThread();
Thread t = new Thread() {
boolean running = true;
public void run() {
try {
// Try to resolve the host name
InetAddress addr = InetAddress.getByName (hostname);
// Successful resolution, notify the waiting thread
if (running) {
// Signal the waiting thread that it can do the HTTP request now
waitingThread.interrupt();
}
} catch (Exception e) {
// Some problem, just ignore it
}
}
};
try {
// Start name resolution
t.start();
// Sleep for as long as we are willing to wait for the DNS resolution
Thread.sleep(4000);
// If we slept the entire time without getting interrupted, the DNS resolution took too long
// so assume we have no connectivity.
t.running = false; // We don't want to be interrupted anymore
// Don't even bother trying the HTTP request now, we've used up all the time we have
} catch (InterruptedException ie) {
// We got interrupted, so the DNS resolution must have been successful. Do the HTTP request now
HttpResponse httpResponse = client.execute(request);
}
Run Code Online (Sandbox Code Playgroud)
我正在编写此代码而不尝试它,所以请原谅任何拼写错误或丢失分号.你应该明白这个想法.
| 归档时间: |
|
| 查看次数: |
1270 次 |
| 最近记录: |