gpt4 book ai didi

Android 忽略 DefaultHttpClient 超时参数

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:03:47 26 4
gpt4 key购买 nike

我遇到了 Android 上 DefaultHttpClient 的超时问题。我正在尝试使用以下代码设置超时:

HttpClient client = new DefaultHttpClient();
HttpParams httpParameters = client.getParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 4000);
HttpConnectionParams.setSoTimeout(httpParameters, 4000);

但是如果设备连接到没有互联网连接的网络,则永远不会触发超时,并且 http 请求的执行永远不会抛出任何超时异常。我正在执行 http 请求如下:

HttpResponse httpResponse = client.execute(request);

我还尝试使用以下几行设置 HttpRequest 的超时:

HttpRequestBase request = ...
request.setParams(httpParameters);

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();
}

但是即使我从日志中看到请求被中止并且连接管理器被关闭,请求的执行也没有被中断/中止并且在超时设置时没有引发异常。请求总是在 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);
}

我是在没有尝试的情况下编写这段代码的,所以请原谅任何拼写错误或遗漏的分号。你应该明白了。

关于Android 忽略 DefaultHttpClient 超时参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27185977/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com