42
Update: Found the answer myself, see below :-)

Hi,

I'am currently coding an android app that submits stuff in the background using HTTP Post and AsyncTask. I use the org.apache.http.client Package for this. I based my code on this example.

Basically, my code looks like this:

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

The problem is that the httpclient.execute(..) line takes around 1.5 to 3 seconds, and I do not understand why. Just requesting a page with HTTP Get takes around 80 ms or so, so the problem doesn't seem to be the network latency itself.

The problem doesn't seem to be on the server side either, I have also tried POSTing data to http://www.disney.com/ with similarly slow results. And Firebug shows 1 ms response time when POSTing data to my server locally.

This happens on the Emulator and with my Nexus One (both with Android 2.2).

If you want to look at the complete code, I've put it on GitHub.

It's just a dummy program to do HTTP Post in the background using AsyncTask on the push of a button. It's my first Android app, and my first java code for a long time. And incidentially, also my first question on Stackoverflow ;-)

Any ideas why httpclient.execute(httppost) takes so long?

pableu
  • 3,200
  • 4
  • 23
  • 21
  • I am experiencing this exact same problem, except much worse. It can even take upwards of 20 seconds to finish an `HttpPost`. I tried your fix but it didn't seem to help. – theblang Mar 13 '14 at 22:00

2 Answers2

55

Allright, I solved this myself with some more investigation. All I had to do was to add a parameter that sets the HTTP Version to 1.1, as follows:

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

I found this thanks to the very nice HttpHelper Class from and-bookworm and some trial-and-error.

If I remember correctly, HTTP 1.0 opens a new TCP connection for every request. Does that explain the large delay?

A HTTP POST request now takes between 50 and 150 ms over WLAN and something between 300 and 500 ms over 3G.

pableu
  • 3,200
  • 4
  • 23
  • 21
  • 2
    tiny bit simpler (but equivalent): HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); – Yaniv Inbar Apr 05 '11 at 14:15
  • 12
    Instead of the version workaround -- why does that work anyway? -- I suggest the more straightforward solution, `httppost.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);` – Liudvikas Bukys Jun 09 '11 at 12:29
  • 1
    dude - i was searching randomly on this topic in between tests for my app because it was so slow - this change made it scream. THANK YOU. – bsautner Jan 14 '13 at 21:17
  • I met the problem too, setting the http version to 1.1 can improve a little. Use HttpURLConnection instead, it's very fast. – Lei Guo Apr 26 '13 at 03:40
  • 1
    @pabelu i guess i stumbled upon this question by accident while trying to figure out something else... and apparently pretty late.. but i guess you were very correct when you said that HTTP/1.0 does actually create a new connection for every new request it sends. And this was once significant change in HTTP/1.1 where you have the concept of 'Persistent Connections', where the connection is not dropped unless explicitly stated. Please ref to the [RFC] (http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html) – qre0ct May 09 '13 at 07:04
6

i am not on android, but i faced exactly the same kind of problem on windows platform with httpclient 4.0.1, after quite a bit of head scratching, i found the solution.

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

i have no idea why setting the parameters with HTTP1.1 version solves the problem. but it does. also even weirder, the symptom did not show if executing an HTTP Get request.

anyhow, i hope this helps some out there !

h

henri
  • 61
  • 1
  • 1