Ir al contenido principal

Un error común es que el TCP garantiza la entrega de los datos. Lo que TCP garantiza en realidad es que entregará los datos a la pila TCP del host receptor o informará de un error a la aplicación de envío. Desafortunadamente, el informe de error no indica cuántos datos se entregaron realmente. También hay una diferencia significativa entre la pila TCP receptora y la aplicación receptora.

Hay dos escenarios básicos de fracaso. En el primero, la pila TCP que envía no está recibiendo los reconocimientos TCP de los datos que está transmitiendo. En este escenario, la aplicación que envía puede continuar llamando a enviar para poner más datos en el búfer de envío de la pila TCP. Una vez que la pila TCP agota el tiempo de transmisión, el siguiente envío (o recepción) llamado por la aplicación de envío indicará el error ETIMEDOUT. La aplicación sabe ahora que hubo un problema pero no tiene idea de cuántos datos se transmitieron con éxito. Éxito significa que la pila TCP emisora recibió un acuse de recibo de los datos de la pila TCP receptora.

En el segundo escenario, la pila TCP que envía transmite datos y recibe un reinicio en lugar de un reconocimiento. El reinicio puede indicar que la pila TCP receptora ha cerrado el zócalo o que algún dispositivo de red, tal vez un cortafuegos, ha caducado. La próxima vez que la aplicación emisora llame a enviar (o a recibir) se indicará el error de ECONNRESET. Se podría pensar que en este escenario la aplicación emisora podría inferir que sólo fallaron los datos de la última llamada de envío, pero estaría equivocado. Es posible que la pila TCP de envío haya almacenado en un búfer los datos de varias llamadas de envío en un segmento TCP y que ese segmento haya disparado el reinicio o que se hayan enviado una serie de segmentos TCP antes de que el reinicio, disparado por el primer segmento de la serie, llegara de nuevo al remitente. Todo lo que la aplicación de envío puede deducir es que no todos los datos se transmitieron con éxito.

Hay un tercer escenario de fallo que no tiene nada que ver con la pila de TCP (envío o recepción) o la red. Supongamos que la aplicación receptora tiene un fallo que le impide leer los datos. La pila TCP receptora seguirá recibiendo los datos y enviará acuses de recibo TCP hasta que el búfer de recepción TCP se llene. Sin embargo, eso puede ser hasta 64K bytes de datos (o más si se admite el escalado de ventanas TCP). Si es necesario reiniciar la aplicación receptora, se perderán todos los datos del búfer de recepción TCP. La pila TCP receptora debería (pero no puede) enviar un reinicio a la pila TCP emisora cuando la aplicación receptora se termina. Enviará un reinicio la próxima vez que reciba un segmento para la conexión ahora cerrada. Desde el punto de vista de la aplicación emisora, esto es similar al segundo escenario. Sin embargo, señala que incluso si la pila TCP receptora reconoce los datos, en caso de error, no es seguro para el remitente asumir que la aplicación receptora ha leído los datos.

La idea que se desprende de estos escenarios de fallo es que sin un reconocimiento de la capa de aplicación, un error de tiempo de transmisión o de reinicio indica que algunos, posiblemente todos los datos transmitidos pueden no haber sido leídos por la aplicación receptora. Por esta razón recomiendo que todas las aplicaciones incluyan acuses de recibo de la capa de aplicación, estén preparadas para restablecer una conexión y retransmitir los datos no reconocidos y sean capaces de tratar los datos duplicados, ya que lo que puede haberse perdido es el acuse de recibo.