2010-06-15 10 views
40
Actualización: encontrado la respuesta a mí mismo, ver a continuación :-)

Hola,Las solicitudes HTTP Post usando HttpClient tardan 2 segundos, ¿por qué?

Soy actualmente la codificación de una aplicación para Android que presenta cosas en el fondo mediante HTTP Post y AsyncTask. Yo uso el paquete org.apache.http.client para esto. Basé mi código en this example.

Básicamente, mi código es el siguiente:

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

El problema es que el httpclient.execute (..) línea de toma alrededor de 1,5 a 3 segundos, y no entiendo por qué. Simplemente solicitando una página con HTTP Get toma alrededor de 80 ms o menos, por lo que el problema no parece ser la latencia de la red en sí.

El problema tampoco parece ser del lado del servidor, también probé datos POST a http://www.disney.com/ con resultados lentos similares. Y Firebug muestra 1 ms de tiempo de respuesta al enviar datos a mi servidor localmente.

Esto sucede en el emulador y con mi Nexus One (ambos con Android 2.2).

Si quiere ver el código completo, lo he puesto en GitHub.

Es solo un programa ficticio hacer una publicación HTTP en segundo plano usando AsyncTask con solo presionar un botón. Es mi primera aplicación de Android y mi primer código de Java durante mucho tiempo. Y por separado, también mi primera pregunta sobre Stackoverflow ;-)

¿Alguna idea de por qué httpclient.execute (httppost) lleva tanto tiempo?

+0

Estoy experimentando exactamente este mismo problema, excepto mucho peor. Incluso puede tomar más de 20 segundos terminar un 'HttpPost'.Probé tu solución pero no pareció ayudar. – theblang

Respuesta

55

Muy bien, lo resolví yo mismo con un poco más de investigación. Todo lo que tenía que hacer era añadir un parámetro que define la versión de HTTP a 1,1, de la siguiente manera:

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

He encontrado esto gracias a la muy agradable HttpHelper Class desde y-ratón de biblioteca y un poco de ensayo y error.

Si no recuerdo mal, HTTP 1.0 abre una nueva conexión TCP para cada solicitud. ¿Eso explica la gran demora?

Una solicitud HTTP POST ahora toma entre 50 y 150 ms en WLAN y algo entre 300 y 500 ms en 3G.

+2

poco más simple (pero equivalente): HttpProtocolParams.setVersion (params, HttpVersion.HTTP_1_1); –

+12

En lugar de la solución de la versión, ¿por qué funciona de todos modos? - Sugiero la solución más directa, 'httppost.getParams(). SetBooleanParameter (CoreProtocolPNames.USE_EXPECT_CONTINUE, false);' –

+1

amigo - estaba buscando aleatoriamente este tema entre pruebas para mi aplicación porque era muy lento - este cambio lo hizo gritar GRACIAS. – bsautner

6

no estoy en Android, pero me enfrenté exactamente al mismo tipo de problema en la plataforma de Windows con httpclient 4.0.1, después de un poco de rasguño en la cabeza, encontré la solución.

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

no tengo idea de por qué establecer los parámetros con la versión HTTP1.1 resuelve el problema. pero lo hace incluso más extraño, el síntoma no se muestra si se ejecuta una solicitud HTTP Get.

de todos modos, espero que esto ayude a algunos por ahí!

h

Cuestiones relacionadas