Los mecanismos que usa TCP para establecer y terminar las conexiones son realmente ingeniosos. |
Entradas de la serie -> TCP/IP
Establecimiento de la conexión
Por lo general, el software TCP en una máquina espera de forma pasiva la petición de conexión iniciada por la otra máquina. Sin embargo, el algoritmo de negociación (handshake) se ha diseñado para que también funcione cuando ambas máquinas inician la conexión al mismo tiempo.
Otra eventualidad que debe tener en cuenta este algoritmo es la naturaleza no confiable de la red IP subyacente. Los datagramas pueden perderse, retrasarse, duplicarse o entregarse en desorden. Estas dos premisas marcan el diseño de la negociación de conexión TCP.
TCP usa una negociación en tres etapas:
1) Un extremo envía un mensaje con el bit SYN de la cabecera TCP activado (petición de conexión).
2) El otro extremo acusa el recibo de éste mediante un mensaje con los bits SYN y ACK activados (petición de conexión y acuse de recibo).
3) El extremo originario devuelve a su vez un mensaje con sólo el bit ACK activado (sólo acuse de recibo).
Establecimiento de la conexión
Por lo general, el software TCP en una máquina espera de forma pasiva la petición de conexión iniciada por la otra máquina. Sin embargo, el algoritmo de negociación (handshake) se ha diseñado para que también funcione cuando ambas máquinas inician la conexión al mismo tiempo.
Otra eventualidad que debe tener en cuenta este algoritmo es la naturaleza no confiable de la red IP subyacente. Los datagramas pueden perderse, retrasarse, duplicarse o entregarse en desorden. Estas dos premisas marcan el diseño de la negociación de conexión TCP.
TCP usa una negociación en tres etapas:
1) Un extremo envía un mensaje con el bit SYN de la cabecera TCP activado (petición de conexión).
2) El otro extremo acusa el recibo de éste mediante un mensaje con los bits SYN y ACK activados (petición de conexión y acuse de recibo).
3) El extremo originario devuelve a su vez un mensaje con sólo el bit ACK activado (sólo acuse de recibo).
Este esquema de negociación impide que la pérdida, desorden o duplicación de estos mensajes pueda llegar a confundir a una de las partes, dejándola en un estado incorrecto.
El protocolo permite además que estos mensajes, que en principio estarían vacíos de datos, puedan transportar ya por adelantado los primeros datos, los cuales serían retenidos sin pasarlos al software de aplicación hasta que se complete la negociación.
Negociación de números de secuencia inicial
En los tres pasos de la negociación, no sólo se ponen de acuerdo los extremos en iniciarla, sino también en qué números de secuencia van a usar inicialmente en cada uno de los flujos de octetos.
* Con el primer SYN, el extremo iniciador envía su número de secuencia inicial x (campo de número de secuencia).
* Con el mensaje SYN/ACK, el otro extremo asiente el valor x+1 en el campo de asentimiento y al mismo tiempo envía su número de secuencia y en el campo de secuencia.
* Por último, el extremo inicial asiente y+1 con su mensaje ACK.
El protocolo permite además que estos mensajes, que en principio estarían vacíos de datos, puedan transportar ya por adelantado los primeros datos, los cuales serían retenidos sin pasarlos al software de aplicación hasta que se complete la negociación.
Negociación de números de secuencia inicial
En los tres pasos de la negociación, no sólo se ponen de acuerdo los extremos en iniciarla, sino también en qué números de secuencia van a usar inicialmente en cada uno de los flujos de octetos.
* Con el primer SYN, el extremo iniciador envía su número de secuencia inicial x (campo de número de secuencia).
* Con el mensaje SYN/ACK, el otro extremo asiente el valor x+1 en el campo de asentimiento y al mismo tiempo envía su número de secuencia y en el campo de secuencia.
* Por último, el extremo inicial asiente y+1 con su mensaje ACK.
La elección de los números a usar es aleatoria. Se hace así para evitar determinados problemas derivados de la reiniciación de conexiones con los mismos números.
Terminación de conexiones
La negociación para la terminación de conexiones es una modificación del algoritmo en tres etapas:
* Uno de los extremos envía un mensaje con el bit FIN de la cabecera activado, indicando además el número de secuencia x final del flujo de octetos.
* El receptor devuelve acuse de recibo (bit ACK) para x+1. Inmediatamente después, informa al programa de usuario del final en el flujo de octetos de entrada.
* Cuando la aplicación decide terminar por su parte la conexión, se envía un mensaje con los bits ACK y FIN activados, indicándose en el campo de asentimiento otra vez x+1 y en el de secuencia el correspondiente al final del flujo y.
* Por último, el extremo que inició el cierre, retorna un ACK para y+1, con lo que queda definitivamente cerrada la conexión, y ambos extremos liberan los registros de la conexión.
Como se puede observar, la segunda etapa ha quedado dividida en dos. Debido a que el hecho de informar al programa de aplicación de la solicitud de cierre y obtener respuesta puede tomar un tiempo considerable, sobre todo si comprende intervención humana, se ha incluido un primer asentimiento que evita la retransmisión del primer mensaje FIN.
Tras este primer asentimiento, el protocolo da por terminado el flujo sólo en un sentido, pudiéndose aún enviar datos en el otro. El flujo recién cerrado rechazará cualquier segmento de datos, aunque aún dejará pasar los acuses de recibo correspondientes a los datos del flujo contrario.
Ruptura anormal de conexiones
A veces se presentan condiciones que obligan a un programa de aplicación o al software de red a interrumpir una conexión.
La secuencia de ruptura es la siguiente:
* El extremo que quiere reiniciar, envía un mensaje con el campo RST activado.
* El otro extremo, inmediatamente cierra la conexión, informando al programa de aplicación del problema
Tras este primer asentimiento, el protocolo da por terminado el flujo sólo en un sentido, pudiéndose aún enviar datos en el otro. El flujo recién cerrado rechazará cualquier segmento de datos, aunque aún dejará pasar los acuses de recibo correspondientes a los datos del flujo contrario.
Ruptura anormal de conexiones
A veces se presentan condiciones que obligan a un programa de aplicación o al software de red a interrumpir una conexión.
La secuencia de ruptura es la siguiente:
* El extremo que quiere reiniciar, envía un mensaje con el campo RST activado.
* El otro extremo, inmediatamente cierra la conexión, informando al programa de aplicación del problema
Puede ser que sea el propio software TCP el que genere el RST, por ejemplo si detecta un estado de operación no previsto en el protocolo o un comportamiento anormal del otro extremo.
ASPECTOS SOBRE EL RENDIMIENTO
Aunque fue diseñado para un entorno de red de redes, donde los retardos son relativamente grandes, diversas investigaciones han demostrado una excelente capacidad de TCP para adaptarse a las más diversas velocidades.
El rendimiento en el uso de una red local Ethernet típica de 10 Mbps es excelente, y se ha demostrado que puede llegar hasta 1 Gbps sin merma de rendimiento.
Síndrome de la ventana tonta
El haber sido desarrollado y probado en el trabajo real durante años es la clave de la fuerza de TCP, lo mismo que IP y otros elementos de la familia de protocolos. Durante su larga historia, TCP se ha tenido que enfrentar a los más diversos problemas, que han ido siendo subsanados a medida que se descubrían.
Uno de los más importantes problemas de rendimiento es el llamado síndrome de la ventana tonta (SWS, silly window syndrome), que se puede presentar cuando emisor y receptor operan a velocidades muy diferentes.
Si el receptor es muy lento procesando la información recibida, enviará acuses de recibo solicitando en el campo ventana tamaños muy pequeños, incluso de un sólo octeto. Si no se hace nada por evitarlo, el receptor adaptará su ventana de transmisión a un octeto y continuará transmitiendo datagramas con un sólo octeto de datos. Esto no viola las normas del protocolo, pero es nefasto para el rendimiento de la red, pues se desperdicia mucho ancho de banda y esfuerzo computacional de las máquinas implicadas.
La ventana tonta también se puede producir por culpa del emisor, por una implementación del protocolo demasiado agresiva, que envíe los datos según le llegan de la capa de aplicación. También un desajuste entre el tamaño de los bloques de datos enviados por una aplicación y el de los segmentos del protocolo puede hacer que último segmento de cada bloque esté casi vacío de datos.
A los datagramas excesivamente pequeños se les ha dado el nombre de pequegramas (del inglés tinygrams).
Prevención del síndrome de la ventana tonta
En los primeros tiempos de TCP, este síndrome era un problema constante. Posteriormente, se han ido desarrollando diversas soluciones heurísticas que hoy en día se utilizan con éxito.
* Prevención en el lado del receptor
La solución en el receptor es retener el envío de los asentimientos hasta que el espacio libre en la ventana de recepción se haya hecho lo suficientemente grande.
La complicación es definir en cada momento qué es lo que se considera suficientemente grande. Normalmente esta cantidad suele ser la mitad de la ventana o el tamaño mayor de un segmento.
Antes de empezar a retardar el acuse de recibo, ha de enviarse uno indicando tamaño de ventana cero, lo cual suspenderá al emisor, permitiendo así que el receptor se recupere a medida que la aplicación cliente va leyendo datos.
El inconveniente del retardo en los acuses de recibo es que, si se retrasa mucho, el emisor dará por perdidos los datos y los retransmitirá, produciendo una carga innecesaria en la red. Otro efecto negativo es la confusión que se puede producir en el emisor al medir los tiempos de ida y vuelta.
Para minimizar estos efectos, el estándar TCP establece un tiempo máximo de retención de asentimientos de 500 milisegundos, recomendándose que se retorne un asentimiento para cada segmento recibido, con el objetivo de facilitar las estimaciones de tiempos de ida y vuelta.
* Prevención en el lado del emisor
La complicación es definir en cada momento qué es lo que se considera suficientemente grande. Normalmente esta cantidad suele ser la mitad de la ventana o el tamaño mayor de un segmento.
Antes de empezar a retardar el acuse de recibo, ha de enviarse uno indicando tamaño de ventana cero, lo cual suspenderá al emisor, permitiendo así que el receptor se recupere a medida que la aplicación cliente va leyendo datos.
El inconveniente del retardo en los acuses de recibo es que, si se retrasa mucho, el emisor dará por perdidos los datos y los retransmitirá, produciendo una carga innecesaria en la red. Otro efecto negativo es la confusión que se puede producir en el emisor al medir los tiempos de ida y vuelta.
Para minimizar estos efectos, el estándar TCP establece un tiempo máximo de retención de asentimientos de 500 milisegundos, recomendándose que se retorne un asentimiento para cada segmento recibido, con el objetivo de facilitar las estimaciones de tiempos de ida y vuelta.
* Prevención en el lado del emisor
La solución equivalente en el lado del emisor es retardar el envío de cada segmento hasta que se hayan acumulado suficientes datos para que el envío sea rentable. A esta técnica se le llama clumping (agrupamiento).
La dificultad está en que el protocolo no puede saber cuánto tardará el programa de usuario en llenar suficientemente el buffer, ni conoce cuál es el retardo mínimo que la aplicación requiere. Si espera demasiado, los retardos serán excesivos, si espera poco, los segmentos serán muy pequeños, empeorando el rendimiento.
La solución que enunció Nagle, ampliamente utilizada, es especialmente elegante y flexible, combinando diferentes retardos según las condiciones de la red en cada momento (self clocking, auto-temporización) con la estimación de las necesidades de la aplicación a partir de la llegada de acuses de recibo desde el receptor.
El procedimiento es el siguiente: cuando una aplicación genera datos adicionales para enviarse sobre una conexión por la que se han transmitido datos recientemente, pero de los cuales no hay aún acuse de recibo, deben retenerse éstos en memoria intermedia hasta que se haya alcanzado el tamaño máximo de un segmento, aún cuando la aplicación haya solicitado una operación push. Si en el intervalo de espera llega un acuse de recibo, se debe desencadenar el envío inmediatamente.
A través de esta técnica se consigue la adaptación a combinaciones arbitrarias de retardos de red, tamaños diversos de segmento y velocidades de las aplicaciones, sin disminuir en general el rendimiento.
La dificultad está en que el protocolo no puede saber cuánto tardará el programa de usuario en llenar suficientemente el buffer, ni conoce cuál es el retardo mínimo que la aplicación requiere. Si espera demasiado, los retardos serán excesivos, si espera poco, los segmentos serán muy pequeños, empeorando el rendimiento.
La solución que enunció Nagle, ampliamente utilizada, es especialmente elegante y flexible, combinando diferentes retardos según las condiciones de la red en cada momento (self clocking, auto-temporización) con la estimación de las necesidades de la aplicación a partir de la llegada de acuses de recibo desde el receptor.
El procedimiento es el siguiente: cuando una aplicación genera datos adicionales para enviarse sobre una conexión por la que se han transmitido datos recientemente, pero de los cuales no hay aún acuse de recibo, deben retenerse éstos en memoria intermedia hasta que se haya alcanzado el tamaño máximo de un segmento, aún cuando la aplicación haya solicitado una operación push. Si en el intervalo de espera llega un acuse de recibo, se debe desencadenar el envío inmediatamente.
A través de esta técnica se consigue la adaptación a combinaciones arbitrarias de retardos de red, tamaños diversos de segmento y velocidades de las aplicaciones, sin disminuir en general el rendimiento.
No hay comentarios:
Publicar un comentario
Expresa tu opinión respetando a los demás y a unas mínimas reglas del lenguaje castellano.
Nota: solo los miembros de este blog pueden publicar comentarios.