使用 HttpClient 的 HTTP Post 请求需要 2 秒,为啥?

Posted

技术标签:

【中文标题】使用 HttpClient 的 HTTP Post 请求需要 2 秒,为啥?【英文标题】:HTTP Post requests using HttpClient take 2 seconds, why?使用 HttpClient 的 HTTP Post 请求需要 2 秒,为什么? 【发布时间】:2010-06-15 15:04:40 【问题描述】:
更新: 自己找到了答案,见下文:-)

你好,

我目前正在编写一个使用 HTTP Post 和 AsyncTask 在后台提交内容的 android 应用程序。我为此使用org.apache.http.client 包。我的代码基于this example。

基本上,我的代码如下所示:

public void postData() 
    // Create a new HttpClient and Post Header
    HttpClient httpclient = new DefaultHttpClient();
    HttpPost httppost = new HttpPost("http://192.168.1.137:8880/form");

    try 
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
        nameValuePairs.add(new BasicNameValuePair("id", "12345"));
        nameValuePairs.add(new BasicNameValuePair("stringdata", "AndDev is Cool!"));
        httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        // Execute HTTP Post Request
        HttpResponse response = httpclient.execute(httppost);

     catch (ClientProtocolException e) 
     Log.e(TAG,e.toString());
     catch (IOException e) 
     Log.e(TAG,e.toString());
    

问题是 httpclient.execute(..) 行大约需要 1.5 到 3 秒,我不明白为什么。仅使用 HTTP Get 请求页面大约需要 80 毫秒左右,因此问题似乎不在于网络延迟本身。

问题似乎也不在服务器端,我也尝试过将数据发布到http://www.disney.com/,结果同样缓慢。 Firebug 在本地将数据发布到我的服务器时显示 1 毫秒的响应时间。

这发生在模拟器和我的 Nexus One(都使用 Android 2.2)上。

如果你想看完整的代码,我已经把它放在GitHub。

这只是一个在后台使用 AsyncTask 进行 HTTP Post 的虚拟程序,只需按一下按钮。这是我的第一个 Android 应用程序,也是我很长一段时间以来的第一个 java 代码。顺便说一句,也是我关于 *** 的第一个问题 ;-)

知道为什么 httpclient.execute(httppost) 需要这么长时间吗?

【问题讨论】:

我遇到了同样的问题,只是更糟。完成HttpPost 甚至可能需要 20 秒以上的时间。我尝试了您的修复方法,但似乎没有帮助。 【参考方案1】:

好的,我自己通过更多调查解决了这个问题。我所要做的就是添加一个将 HTTP 版本设置为 1.1 的参数,如下所示:

HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpClient httpclient = new DefaultHttpClient(params);

感谢 and-bookworm 提供的非常好的 HttpHelper Class 和一些反复试验,我发现了这一点。

如果我没记错的话,HTTP 1.0 会为每个请求打开一个新的 TCP 连接。这是否解释了大的延迟?

现在,通过 WLAN 的 HTTP POST 请求需要 50 到 150 毫秒,而通过 3G 则需要 300 到 500 毫秒。

【讨论】:

稍微简单一点(但等效):HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 而不是版本解决方法——为什么它仍然有效? -- 我建议更直接的解决方案,httppost.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false); 老兄——我在测试我的应用程序之间随机搜索这个主题,因为它太慢了——这个变化让它尖叫。谢谢。 我也遇到了这个问题,设置http版本为1.1可以改善一点。改用 HttpURLConnection,速度非常快。 @pabelu 我想我在试图找出其他东西时偶然发现了这个问题......而且显然已经很晚了......但我猜你说 HTTP/1.0 确实是正确的实际上为它发送的每个新请求创建一个新连接。这曾经是 HTTP/1.1 中的重大变化,您有“持久连接”的概念,除非明确说明,否则连接不会被丢弃。请参考 [RFC] (w3.org/Protocols/rfc2616/rfc2616-sec8.html)【参考方案2】:

我不在android上,但我在windows平台上使用httpclient 4.0.1遇到了完全相同的问题,经过一番摸索后,我找到了解决方案。

HttpParams params = new BasicHttpParams();
//this how tiny it might seems, is actually absoluty needed. otherwise http client lags for 2sec.
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpClient httpClient = new DefaultHttpClient(params);
HttpResponse httpResponse;


HttpPost httpPost = new HttpPost("http://"+server+":"+port+"/");
StringEntity entity = new StringEntity(content, "utf-8");
entity.setContentType("text/plain; charset=utf-8"); 
httpPost.setEntity(entity);

httpResponse=httpClient.execute(httpPost);

String response = IOUtils.toString(httpResponse.getEntity().getContent(),encoding);
httpResponse.getEntity().consumeContent();

httpClient.getConnectionManager().shutdown();
return(response);

我不知道为什么使用 HTTP1.1 版本设置参数可以解决问题。但确实如此。 更奇怪的是,如果执行 HTTP Get 请求,症状不会显示。

无论如何,我希望这可以帮助一些人!

h

【讨论】:

以上是关于使用 HttpClient 的 HTTP Post 请求需要 2 秒,为啥?的主要内容,如果未能解决你的问题,请参考以下文章

使用 HttpClient 的 HTTP Post 请求需要 2 秒,为啥?

HttpClient的Post请求数据

Android--httpclient模拟post请求和get请求

Java使用HttpClient实现Post请求

HttpClient使用详解与实战一:普通的GET和POST请求

HttpClient使用详解与实战一:普通的GET和POST请求