安卓 - 定期出现HttpClient超时问题

5

你好,我之前已经问过这个问题了,但是这次我检查了一下允许所有证书的方法,发现没有引起问题。

我正在开发一个应用程序,也在iPhone上使用。问题出在API请求上。我为所有请求设置了超时时间。有时会出现30到60秒的中断。看起来是应用程序做了几个请求然后就中断了,一直超时,大约45秒后才恢复正常。

我不知道这是服务器问题还是Android的问题。

这个问题在IOS 5的iPhone上没有出现,但在IOS 4上也出现了。

我检查了HttpClient和HttpsURLConnection。

连接是https,我也尝试了直接使用IP地址。

所有请求都有同样的问题,所有请求都在异步任务中。

它们都看起来一样:

DefaultHttpClient client = new HttpSupport().getNewHttpClient();

    client.getCredentialsProvider().setCredentials(new AuthScope(AuthScope.ANY_HOST,AuthScope.ANY_PORT),new UsernamePasswordCredentials(user, pass));

    HttpGet httget = new HttpGet("xxxxxxxxxxxxxxxxxxxxxxx");
    httget.setHeader("Accept", "application/json");

    HttpResponse respond = null;  

    try 
    {
        respond = client.execute(httget);
    } 
    catch (ClientProtocolException e) 
    {
        Log.e(TAG,"getEvents, ClientProtocolException");
    } 
    catch (IOException e) 
    {           
        Log.e(TAG,"getEvents, IOException: " + e.getMessage());
    }

我的HttpSupport类的代码在我之前的问题中:Android - API Requests

这可能是服务器的问题吗? 感谢您的任何帮助。

最近,我注意到应用程序卡在client.execute上......尝试像这样操作:android httpclient hangs on second request to the server (connection timed out),但没有帮助。也许不是api的问题,而是Android本身的问题。这个应用程序经常指向api,但对于大多数请求来说一切都很好。

仍然无法摆脱30-45秒的挂起。

今天我再次测试了应用程序,我注意到错误只发生在三星平板电脑上的Wi-Fi连接(3.2版本)。在Wildfire上使用2.3.7版本(Wi-Fi和3g)似乎一切正常。我并不是说在移动设备上不会出现问题,但在测试时我并没有注意到超时。

2个回答

4

您的客户端超时设置太短了 - 在移动连接上,您应该预计需要多达30秒才能建立连接,并在此之后再等待30秒以接收响应。

您的代码(通过您的链接):

int timeoutConnection = 3000;
        HttpConnectionParams.setConnectionTimeout(params, timeoutConnection);
        // Set the default socket timeout (SO_TIMEOUT) 
        // in milliseconds which is the timeout for waiting for data.
        int timeoutSocket = 5000;
        HttpConnectionParams.setSoTimeout(params, timeoutSocket);

这是毫秒为单位的。所以,如果您的连接超时时间为3秒,响应时间为5秒。

我建议将它们分别改为30000和60000。

此外,如果您想排除任何服务器问题,请安装类似fiddler2之类的HTTP代理,并使用它显示每个HTTP/HTTPS请求,您将看到每个服务器响应。然后您可以看到是客户端还是服务器出现了问题。


你确定时间没问题吗?即使我使用Wi-Fi连接设备,API的人员也会在0.5秒内发送响应时间,但我仍然遇到了这个问题。 - goodm
虽然这不完全是你的问题,但它们肯定太简短了,无法涵盖你可能遇到的所有连接方案。因此,我建议使用 Fiddler 进行调试 - 它将有助于确定问题所在。 - peterept
不幸的是,即使我改变超时时间,也无法解决我的问题,它只会延长等待时间。 - goodm
糟糕。好的,拿一台Windows电脑,下载Fiddler2。运行它。打开首选项并启用它以监听端口(比如8888),同时启用HTTPS拦截。然后将您的手机设置为使用Wifi(与PC相同的网络),并在Wifi上启用HTTP代理,将其指向PC的IP地址和端口8888。然后再次运行您的应用程序,并在Fiddler中获取登录日志。如果不明显,请在此处发布日志。 - peterept
我将在回家后立即完成,因为我们在工作室使用的是苹果电脑,而我的私人电脑是Windows操作系统。 - goodm

2
我不清楚你问题的具体解释,但我查看了你的代码并认为其中存在一些设计缺陷,可能会隐藏一些潜在的错误,而开发人员应该在编译时就注意到这些问题,而不是让它们在运行时泄漏出来。
在你的HttpSupport.getNewHttpClient()实现中:
public DefaultHttpClient getNewHttpClient() {
  try {
    ... ...

    ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

    return new DefaultHttpClient(ccm, params);
  } catch (Exception e) {
    return new DefaultHttpClient();
}

在try和catch块中,您都返回了一个HttpClient实例,其中来自try块的实例返回了一个强大的HttpClient,它知道访问远程HTTP服务器所使用的正确协议、凭据等。当发生异常时,在catch块中返回另一个裸露的HttpClent有什么意义呢?异常通常意味着发生了一些预期的错误,并且应该在编译时由开发人员处理,而您所做的只是忽略所有有用的警告,并让它们在应用程序运行时泄漏,更糟糕的是,没有可见性来知道发生了什么。

因此,第一次尝试解决您的问题是更改您的代码以正确处理异常,简单地打印出异常堆栈跟踪,并查找在创建/初始化HttpClient时可能存在的潜在问题。

我想提到的另一点是,您是按需创建/初始化HttpClient,也就是说,每次需要发送HTTP请求时都会创建和初始化新的HttpClient实例,这可能与您的问题无关,但在我看来效率低下。

我的感觉是,您的问题可能与在多线程环境中创建/初始化HttpClient有关(因为您说您使用了AsyncTask),因为HttpClient不是线程安全的。希望这可以帮助您。


是的,我正在思考这个问题,但是当我在catch异常中放置Log.e(“HttpClient”,e.toString());时,它从未出现在我的Logs中。因此,这不是造成这个问题的原因。我开始假设这是服务器的错误而不是应用程序的错误。 - goodm
然而,在 catch 块中返回裸的 HttpClient 是绝对荒谬的。你的应用程序如何发起 HTTP 请求?你的应用程序中是否有同时生成和发起多个 HTTP 请求的地方(通过 AsyncTask)? - yorkw

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