¿Por qué DefaultHttpClient envía datos a través de un socket semi-cerrado?

Estoy utilizando DefaultHttpClient con un ThreadSafeClientConnManager en Android (2.3.x) para enviar solicitudes HTTP a un servidor REST (embarcado Jetty).

Después de ~ 200 segundos de tiempo de inactividad, el servidor cierra la conexión TCP con un [FIN]. El cliente de Android responde con un [ACK]. Esto debería dejar el socket en un estado medio cerrado (el servidor sigue escuchando, pero no puede enviar datos).

Espero que cuando el cliente intente usar esa conexión otra vez (vía HttpClient.execute ), DefaultHttpClient detectaría el estado semicerrado, cierre el zócalo en el lado del cliente (así que el enviarlo es [FIN / ACK] para finalizar el cierre) , Y abra una nueva conexión para la solicitud. Pero, está el frotamiento.

En su lugar, envía la nueva solicitud HTTP sobre el socket semi-cerrado. Sólo después del envío se detecta el estado semi-cerrado y se cierra el socket en el lado del cliente (con el [FIN] enviado al servidor). Por supuesto, el servidor no puede responder a la solicitud (ya había enviado su [FIN]), por lo que el cliente cree que la solicitud ha fallado y vuelve a intentar automáticamente a través de un nuevo socket / conexión.

El resultado final es que el servidor ve y procesa dos copias de la solicitud.

¿Alguna idea sobre cómo solucionar este problema? (Mi servidor hace lo correcto con la segunda copia, pero me molesta que la carga útil se transmita dos veces).

¿No debería DefaultHttpClient detectar que el zócalo se cerró cuando primero intenta escribir el nuevo paquete HTTP, cierre ese zócalo inmediatamente, e inicie uno nuevo? Estoy desconcertado en cuanto a cómo una nueva solicitud HTTP se envía en un socket minutos después de que el servidor envió un [FIN].

Esta es una limitación general de la E / S de bloqueo en Java. Simplemente no hay manera de averiguar si el punto final opuesto tiene o no conexión cerrada, aparte de intentar leer desde el socket. Apache HttpClient trabaja este problema con el empleo de la verificación de conexión tan rancio que es esencialmente una operación de lectura muy breve. Sin embargo, el cheque puede ya menudo está inhabilitado. De hecho, a menudo es aconsejable tenerlo inhabilitado debido a la latencia adicional que el cheque introduce. No tengo ni idea de cómo exactamente la versión de HttpClient enviada con Android se comporta a este respecto, pero podría intentar explícitamente habilitar la comprobación mediante un parámetro de configuración adecuado.

Una mejor solución a este problema podría ser desalojar las conexiones del grupo de conexiones que han estado inactivas durante un período de tiempo determinado (digamos 150 segundos) después de un período de inactividad.

http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d5e652

  • Android VpnService - ¿Cómo reenviar el tráfico interceptado de Internet?
  • Conexiones de socket y Polling. ¿Cuál es la mejor solución en términos de duración de la batería?
  • Aplicación de depuración que utiliza ADB sobre Bluetooth para un netbook Android-x86
  • No se puede conectar al servidor Openfire (mediante smack api)
  • ¿Android 4.x soporta streaming RTSP sobre TCP?
  • Conexión adb sobre tcp no funciona ahora
  • ¿Cómo hacer cliente en Android escuchar al servidor en C #?
  • ¿Problemas con el uso de TCP y UDP en la misma aplicación?
  • Mensajería instantánea sobre xmpp o websocket
  • Cliente TCP muy simple
  • Socket IPv6 en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.