¿Por qué necesitamos un apretón de manos de 3 vías? ¿Por qué no solo de 2 vías?

124

El protocolo de enlace TCP de 3 vías funciona así:

Client ------SYN-----> Server
Client <---ACK/SYN---- Server
Client ------ACK-----> Server

¿Por qué no solo esto?

Client ------SYN-----> Server
Client <-----ACK------ Server
smwikipedia
fuente
24
¿Por qué necesitamos un apretón de manos? ¿Por qué no se puede enviar el mensaje con el primer paquete?
Mehrdad el
44
Si desea omitir el apretón de manos, puede usar UDP en su lugar.
OzNetNerd
55
@Mehrdad, si tiene una pregunta propia, utilice el enlace Hacer pregunta en la parte superior de la página para publicar la suya.
YLearn
40
@YLearn: Lo siento, en realidad no es una pregunta mía, sino que fue para motivar a los lectores a dar respuestas que profundicen un poco más de lo que se dice literalmente en la pregunta.
Mehrdad
3
No se olvide de TCP Fast Open (RFC 7413)
Alnitak

Respuestas:

160

Divide el apretón de manos en lo que realmente está haciendo.

En TCP, las dos partes realizan un seguimiento de lo que han enviado utilizando un número de secuencia. Efectivamente, termina siendo un recuento de bytes en ejecución de todo lo que se envió. La parte receptora puede usar el número de secuencia del hablante opuesto para reconocer lo que ha recibido.

Pero el número de secuencia no comienza en 0. Comienza en el ISN (Número de secuencia inicial), que es un valor elegido al azar. Y dado que TCP es una comunicación bidireccional, ambas partes pueden "hablar" y, por lo tanto, ambas deben generar aleatoriamente un ISN como su Número de secuencia inicial. Lo que a su vez significa que ambas partes deben notificar a la otra parte de su ISN inicial.

Entonces terminas con esta secuencia de eventos para comenzar una conversación TCP entre Alice y Bob:

Alice ---> Bob    SYNchronize with my Initial Sequence Number of X
Alice <--- Bob    I received your syn, I ACKnowledge that I am ready for [X+1]
Alice <--- Bob    SYNchronize with my Initial Sequence Number of Y
Alice ---> Bob    I received your syn, I ACKnowledge that I am ready for [Y+1]

Observe que están ocurriendo cuatro eventos:

  1. Alice elige un ISN y lo SINCRONIZA con Bob.
  2. Bob AC conoce al ISN.
  3. Bob elige un ISN y lo SINCRONIZA con Alice.
  4. Alice AC conoce al ISN.

Sin embargo, en realidad, los dos eventos intermedios (# 2 y # 3) ocurren en el mismo paquete. Lo que hace que un paquete sea un SYNo ACKsimplemente un indicador binario activado o desactivado dentro de cada encabezado TCP , por lo que no hay nada que impida que ambos indicadores se habiliten en el mismo paquete. Entonces el apretón de manos de tres vías termina siendo:

Bob <--- Alice         SYN
Bob ---> Alice     SYN ACK 
Bob <--- Alice     ACK     

Observe las dos instancias de "SYN" y "ACK", una de cada una, en ambas direcciones.


Entonces, para volver a su pregunta, ¿por qué no usar un apretón de manos de dos vías? La respuesta corta es porque un apretón de manos de dos vías solo permitiría que una parte establezca un ISN y la otra parte lo reconozca. Lo que significa que solo una parte puede enviar datos.

Pero TCP es un protocolo de comunicación bidireccional, lo que significa que cualquiera de los extremos debería poder enviar datos de manera confiable. Ambas partes deben establecer un ISN, y ambas partes deben reconocer el ISN de la otra.

En efecto, lo que tiene es exactamente su descripción del apretón de manos de dos vías, pero en cada dirección . Por lo tanto, se producen cuatro eventos. Y nuevamente, las dos banderas del medio ocurren en el mismo paquete. Como tales tres paquetes están involucrados en un proceso de inicio de conexión TCP completo.

Eddie
fuente
66
¿Por qué necesitamos ISN en absoluto? Los humanos no lo necesitan, ¿por qué las computadoras? ¿Hay alguna prueba de esto, o simplemente los tenemos porque son convenientes?
Mehrdad el
19
@Mehrdad: necesita números de secuencia para que las retransmisiones funcionen correctamente (o de hecho). El ISN no puede ser simplemente cero debido a los ataques de predicción de secuencia .
Kevin
44
@Mehrdad La sala de chat no necesariamente tiene que ser 'en tiempo real', podemos dejarnos mensajes el uno al otro. La razón por la que pensé dirigirlo a otra parte es porque ahora estás haciendo una pregunta diferente. El OP preguntó "por qué es un apretón de manos de 3 vías en lugar de 2", pero ahora se pregunta "por qué necesitamos números de secuencia", que es diferente. En lugar de descarrilar este hilo, pensé que deberíamos discutir la otra pregunta en el chat. Alternativamente , puede publicar una nueva pregunta, estoy seguro de que obtendrá algunas buenas respuestas.
Eddie
44
Gran respuesta concisa. Leer "ACK SYN" se siente fundamentalmente mal pero incluso explicaste que +1
Lilienthal
3
De acuerdo con RFC 793, Protocolo de Control de Transmisión : " La razón principal del apretón de manos de tres vías es evitar que las viejas iniciaciones de conexión duplicadas causen confusión " .
Ron Maupin
23

El enlace de tres vías es necesario porque ambas partes deben syn chronize sus números de secuencia de segmentos utilizados durante su transmisión. Para ello, cada uno de ellos envía (a su vez) un segmento SYN con un número de secuencia se establece en un valor aleatorio n , que luego se ack nowledged por la otra parte a través de un segmento ACK con un número de secuencia se establece en n + 1 .

dr01
fuente
¿Por qué se necesita el reconocimiento?
Paŭlo Ebermann el
44
@ PaŭloEbermann: Porque de lo contrario, el Servidor no tiene idea de si el cliente alguna vez recibió el SYN, y es importante que el cliente lo reciba.
Mooing Duck el
2
@ PaŭloEbermann Y para demostrarlo, el paso ACK es reconocer con [X + 1]. - Citado del Eddiecomentario de su respuesta.
smwikipedia
14

Para que la conexión funcione, cada lado debe verificar que puede enviar paquetes al otro lado. La única manera de asegurarse de que tiene un paquete al otro lado es obtener un paquete de ellos que, por definición, no se hubiera enviado a menos que el paquete que envió se haya enviado . TCP utiliza esencialmente dos tipos de mensajes para esto: SYN (para solicitar la prueba de que este paquete pasó) y ACK (que solo se envía después de que un SYN pasa, para probar que SYN pasó). En realidad hay un tercer tipo de mensaje, pero llegaremos a eso en un momento.

Antes de que comience la conexión, ninguno de los lados sabe realmente nada del otro. El cliente envía un paquete SYN al servidor, para solicitar pruebas de que sus mensajes pueden pasar . Eso no le dice nada a ninguna persona, pero es el primer paso del apretón de manos.

Si el SYN pasa, entonces el servidor sabe que el cliente puede enviarle paquetes, porque, bueno, simplemente sucedió. Pero eso no prueba que el servidor pueda enviar paquetes de vuelta: los clientes pueden enviar SYN por muchas razones . Por lo tanto, el servidor debe enviar dos mensajes de regreso al cliente: un ACK (para demostrar que el SYN logró pasar) y un SYN (para solicitar un ACK propio). TCP combina estos dos mensajes en uno, un mensaje SYN-ACK, si lo desea, para reducir el tráfico de red. Este es el segundo paso del apretón de manos.

Debido a que un SYN-ACK es un ACK, el cliente ahora sabe con certeza que puede enviar paquetes al servidor. Y debido a que un SYN-ACK es un SYN, también sabe que el servidor quiere pruebas de que este mensaje llegó. Por lo tanto, devuelve un ACK: solo un ACK simple esta vez, porque ya no necesita pruebas de que sus paquetes puedan pasar. Este es el paso final del apretón de manos: el cliente ahora sabe que los paquetes pueden ir en ambos sentidos, y que el servidor está a punto de resolver esto (porque sabe que el ACK pasará).

Una vez que ese ACK pasa, ahora el servidor sabe que puede enviar paquetes al cliente . También sabe que el cliente lo sabe, por lo que puede comenzar a enviar datos de inmediato. El apretón de manos está completo. Tenemos un buen canal

Bueno, estrictamente hablando, no podemos estar seguros de tener un buen canal . El hecho de que esta secuencia de paquetes haya pasado no garantiza estrictamente que otros lo harán. No podemos probar eso sin enviar un número infinito de SYN y ACK, y luego nada más se haría, por lo que esa no es realmente una opción práctica. Pero en la práctica, tres pasos resultan ser lo suficientemente buenos para la mayoría de los propósitos .

El más cuchara
fuente
Esto no es cierto: "un ACK (que solo se envía en respuesta a SYN y, por lo tanto, demuestra que el SYN pasó)". Solo el primer paquete enviado desde cada extremo tiene establecido el indicador SYN, y todos los paquetes que no sean el primer paquete del protocolo de enlace de 3 vías tienen establecido el indicador ACK. El primer paquete no puede ACK porque la segunda parte aún no se ha SINCRONIZADO, pero cada paquete posterior al primero debe ACK lo que ya se haya recibido del otro extremo, ya sea que se envíe o no algún dato.
Monty Harder
Gracias. Reescritura: los ACK se envían una vez que un SYN pasa, en lugar de enviarse solo en respuesta a los SYN.
The Spooniest
Esta es la mejor respuesta que puede explicar lógicamente por qué incluso necesitamos el tercer mensaje. Gracias, Spooniest.
Parth Patel
7

En realidad, un apretón de manos de 3 vías no es el único medio para establecer una conexión TCP. También se permite el intercambio simultáneo de SYN: http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentProcessTheThreeWayHandsh-4.htm

Eso podría verse como una especie de doble apretón de manos de dos vías.

Lexelby
fuente
1
Buen punto, sin embargo, esto es muy raro ya que ambos dispositivos tendrán que usar el mismo puerto de origen / destino y ambos dispositivos deberán enviar un SYN antes de que el otro reciba el SYN. Incluso cuando ocurre, involucra el envío de cuatro paquetes, que es más que los tres paquetes requeridos por el tradicional apretón de manos de 3 vías; en última instancia, solo la posibilidad de ser un poco más rápido de configurar en términos de tiempo general a costa de una menor eficiencia general (requiere un 33% más de paquetes para ser transmitidos).
YLearn
4

La conexión TCP es bidireccional. Lo que esto significa es que en realidad es un par de conexiones unidireccionales. El iniciador envía SYN, el respondedor envía ACK: comienza una conexión simplex. "Entonces" el respondedor envía SYN, el iniciador envía ACK: comienza otra conexión simplex. Dos conexiones simples forman una sesión TCP dúplex, ¿de acuerdo? Entonces, lógicamente, hay cuatro pasos involucrados; pero debido a que los indicadores SYN y ACK son diferentes "campos" del encabezado TCP, se pueden configurar simultáneamente: el segundo y el tercer paso (de los cuatro) se combinan, por lo que técnicamente hay tres intercambios de paquetes. Cada conexión simple (media) usa intercambio bidireccional, como usted propuso.

Sergio
fuente
2

Si el servidor y el cliente desean crear una conexión, deben confirmar cuatro cosas:

  1. El servidor debe confirmar que puede recibir el paquete del Cliente
  2. El cliente debe confirmar que puede recibir el paquete del servidor

  3. El cliente necesita confirmar algo: el servidor puede recibir paquetes del cliente

  4. El servidor necesita confirmar algo: el cliente puede recibir paquetes del servidor

Después Client ------SYN-----> Server, se confirma la regla 1.

Después Client <---ACK/SYN---- Server, se confirman las reglas 2 y 3.

Entonces, se necesita un tercer paquete para confirmar la regla 4.

codeman-cs es mi id de github
fuente
1

No es necesario en absoluto. Es obvio que un mensaje corto solo debe requerir un paquete para el servidor que incluye el mensaje de inicio +, y un paquete de regreso que lo reconozca.

Las respuestas anteriores solo describen el sistema sin discutir la necesidad de números de secuencia aleatorios, etc. en primer lugar. La pregunta original era sobre el diseño del propio TCP: obviamente, si usa el protocolo TCP, entonces necesita tres mensajes porque ese es el protocolo. Pero, ¿por qué se diseñó TCP de esa manera en primer lugar?

Creo que la idea original era que no había distinción entre clientes y servidores. Ambos conocían los puertos del otro de manera bidireccional, y cualquiera podía comenzar la conversación. Y eso requería Syns, etc.

Pero esto no es, por supuesto, cómo se usa hoy. El servidor escucha en un puerto conocido y lo hace y "acepta", el número de puerto del cliente es efímero. Ni siquiera creo que sea posible que un servidor que espera un "aceptar" envíe una solicitud a otro en el mismo número de puerto del cliente en los sistemas operativos normales.

(Tenga en cuenta que esto se trata del inicio bidireccional de la conexión, lo que nunca se hace hoy en día. Eso es muy diferente de enviar mensajes bidireccionales a través de una conexión una vez establecida).

Para evitar la ineficiencia de TCP, utilizamos protocolos como HTTP 1.1 que pueden reutilizar la misma conexión para múltiples solicitudes, y así evitar el protocolo de enlace TCP que no era necesario en primer lugar.

Pero Http 1.1 es relativamente nuevo. Y SSL / TLS necesitaba una forma de reutilizar la sesión desde el principio debido al costo de los algoritmos PKI. De modo que ese protocolo incluye su propio mecanismo de reutilización de sesión que se ejecuta sobre Http 1.1 que se ejecuta sobre TCP.

Tal es el camino con el software. Fudges en kludges que, cuando se combinan, producen un resultado aceptable.

Manejable
fuente
Cualquier cosa por encima de la capa 4 de OSI (por ejemplo, HTTP, FTP, etc.) está explícitamente fuera de tema aquí. En las capas 1 a 4, no existe el cliente / servidor. TCP es una conexión entre pares. Sí, los protocolos de capa superior crean una relación cliente / servidor, pero eso está fuera de tema aquí.
Ron Maupin
1
Por cierto, HTTP usa TCP, por lo que el protocolo de enlace TCP sigue siendo necesario. Lea el PROTOCOLO DE CONTROL DE TRANSMISIÓN RFC 793 para comprender por qué. Los protocolos como HTTP requieren que la aplicación realice la multiplexación que TCP normalmente haría para la aplicación.
Ron Maupin
@RonMaupin La pregunta original era ¿por qué? Y la respuesta es apoyar un caso de uso que nunca es utilizado por las capas de nivel superior en la práctica. Entonces, parece bastante relevante.
Se
@RonMaupin Sí, HTTP usa TCP. Lo cual he aclarado, gracias. Pero eso no hace que el protocolo de enlace TCP sea necesario en ningún sentido profundo.
Se
1
Las aplicaciones y los protocolos de la capa de aplicación están explícitamente fuera de tema aquí. @Eddie respondió la pregunta, y si lees y entiendes el TCP RFC, sabrás por qué es necesario el apretón de manos. No creo que agregue nada para que usted pueda afirmar, sin ningún tipo de apoyo, que el apretón de manos no es necesario, cuando claramente lo es.
Ron Maupin
1

Después de leer la respuesta de Eddie (aceptado como correcto), todavía hay dudas de por qué el primer host no puede asignar ambos ISN con números aleatorios y el segundo simplemente lo acepta. La verdadera razón del uso del apretón de manos de 3 vías es evitar las medias conexiones . Escenario de media conexión en protocolo de enlace bidireccional:
1) Cliente --- SYN -> Servidor
2) El cliente cambia de opinión y ya no quiere conectarse
3) Cliente <-X-ACK-- Servidor // Se perdió ACK
El servidor no ve SYN reenviado, por lo que cree que el cliente recibió su ACK y se estableció la conexión. Como resultado, el servidor tiene una conexión que nunca se cerrará

Sanzhar Yeleuov
fuente
En realidad, si un host (los clientes y los servidores son un concepto de aplicación sobre el cual TCP no sabe nada) recibe un ACK o cualquier tráfico en una conexión inexistente (paso 3 en su escenario), enviará un RST, no ignorará el segmento recibido .
Ron Maupin
@RonMaupin Entonces asumamos la situación cuando se perdió el paquete ACK.
Sanzhar Yeleuov
Si se pierde el ACK, la conexión iniciada en el paso 1 expirará. RFC 793 tiene una explicación completa de todos los tipos de escenarios, incluidos los diagramas.
Ron Maupin
@RonMaupin Quiero decir que si el escenario de mi publicación sigue siendo el mismo, lo único que cambió fue que ACK se perdió.
Sanzhar Yeleuov
Todo está en el RFC. Hasta que se abra una conexión, cualquier tráfico recibido dará como resultado un RST. El protocolo de enlace de tres vías negocia los parámetros de conexión, por lo que el "servidor" no puede enviar nada al "cliente", pero es SYN / ACK hasta que recibe un ACK del "cliente". Si el SYN / ACK "servidor" vuelve al "cliente" se pierde, el "servidor" lo intentará nuevamente. El RFC explica todo esto.
Ron Maupin