Perché abbiamo bisogno di una stretta di mano a 3 vie? Perché non solo 2 vie?


124

L'handshake a 3 vie TCP funziona in questo modo:

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

Perché non solo questo?

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

24
Perché abbiamo persino bisogno di una stretta di mano? Perché il messaggio non può essere inviato con il primo pacchetto?
Mehrdad,

4
Se si desidera saltare la stretta di mano, è possibile utilizzare UDP.
OzNetNerd,

5
@Mehrdad, se hai una tua domanda, ti preghiamo di utilizzare il link Poni domanda nella parte superiore della pagina per pubblicare la tua.
YLearn

40
@YLearn: Mi dispiace, non è davvero una mia domanda, ma piuttosto è stato quello di motivare i lettori a dare risposte che scavano un po 'più in profondità di quanto è letteralmente affermato nella domanda.
Mehrdad,

3
Non dimenticare TCP Fast Open (RFC 7413)
Alnitak,

Risposte:


160

Abbassa la stretta di mano in ciò che sta realmente facendo.

In TCP, le due parti tengono traccia di ciò che hanno inviato utilizzando un numero di sequenza. In effetti finisce per essere un conteggio dei byte in esecuzione di tutto ciò che è stato inviato. La parte ricevente può utilizzare il numero progressivo dell'altoparlante opposto per riconoscere ciò che ha ricevuto.

Ma il numero di sequenza non inizia da 0. Inizia da ISN (Initial Sequence Number), che è un valore scelto casualmente. E poiché TCP è una comunicazione bidirezionale, entrambe le parti possono "parlare", e quindi entrambe devono generare in modo casuale un ISN come numero di sequenza iniziale. Il che a sua volta significa che entrambe le parti devono comunicare all'altra parte il loro ISN iniziale.

Quindi finisci con questa sequenza di eventi per l'inizio di una conversazione TCP tra Alice e 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]

Si noti che si stanno verificando quattro eventi:

  1. Alice sceglie un ISN e lo sincronizza con Bob.
  2. Bob ACK riconosce l'ISN.
  3. Bob sceglie un ISN e lo sincronizza con Alice.
  4. Alice ACK riconosce l'ISN.

In realtà, tuttavia, i due eventi centrali (n. 2 e n. 3) si verificano nello stesso pacchetto. Ciò che rende un pacchetto un SYNo ACKè semplicemente un flag binario attivato o disattivato all'interno di ciascuna intestazione TCP , quindi non c'è nulla che impedisca l'abilitazione di entrambi questi flag sullo stesso pacchetto. Quindi la stretta di mano a tre vie finisce per essere:

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

Notare le due istanze di "SYN" e "ACK", una per ciascuna, in entrambe le direzioni.


Quindi, per tornare alla tua domanda, perché non usare semplicemente una stretta di mano a due vie? La risposta breve è perché una stretta di mano a due vie consentirebbe a una sola parte di stabilire un ISN e l'altra parte di riconoscerlo. Ciò significa che solo una parte può inviare dati.

Ma TCP è un protocollo di comunicazione bidirezionale, il che significa che entrambe le estremità dovrebbero essere in grado di inviare dati in modo affidabile. Entrambe le parti devono stabilire un ISN ed entrambe le parti devono riconoscere l'ISN dell'altro.

Quindi, in effetti, quello che hai è esattamente la tua descrizione della stretta di mano a due vie, ma in ogni direzione . Quindi, si verificano quattro eventi. E ancora, le due bandiere centrali si trovano nello stesso pacchetto. Poiché tali tre pacchetti sono coinvolti in un processo completo di avvio della connessione TCP.


6
Perché abbiamo assolutamente bisogno degli ISN? Gli umani non ne hanno bisogno, perché i computer? C'è una prova di questo o li abbiamo solo perché sono convenienti?
Mehrdad,

19
@Mehrdad: hai bisogno di numeri di sequenza affinché le ritrasmissioni funzionino correttamente (o addirittura affatto). L'ISN non può essere solo zero a causa degli attacchi di previsione della sequenza .
Kevin,

4
@Mehrdad La chat room non deve necessariamente essere "in tempo reale", possiamo lasciare messaggi l'uno per l'altro. Il motivo per cui ho pensato di dirigerlo altrove è perché ora stai facendo una domanda diversa. L'OP ha chiesto "perché si tratta di una stretta di mano a 3 vie invece di 2", ma ora ci si chiede "perché abbiamo bisogno di numeri di sequenza", che è diverso. Piuttosto che deragliare questa discussione, ho pensato che dovremmo discutere l'altra domanda in chat. In alternativa , puoi pubblicare una nuova domanda, sono sicuro che fornirà alcune buone risposte.
Eddie,

4
Ottima, concisa risposta. Leggere "ACK SYN" è fondamentalmente sbagliato ma lo hai anche spiegato +1.
Lilienthal,

3
Secondo RFC 793, Protocollo di controllo della trasmissione : " Il motivo principale della stretta di mano a tre vie è di evitare confusioni da parte di vecchie connessioni duplicate " .
Ron Maupin

23

La stretta di mano a tre vie è necessario in quanto entrambe le parti devono syn chronize i loro numeri di sequenza di segmenti utilizzati durante la loro trasmissione. Per questo, ciascuno di essi manda (a sua volta) un segmento SYN con un numero di sequenza impostata su un valore casuale n , che poi viene ack nowledged dall'altra parte con un segmento ACK con un numero di sequenza impostato a n + 1 .


Perché è necessario il riconoscimento?
Paŭlo Ebermann,

4
@ PaŭloEbermann: Perché altrimenti il ​​Server non ha idea se il client abbia mai ricevuto il SYN, ed è importante che il client lo riceva.
Mooing Duck il

2
@ PaŭloEbermann E per dimostrarlo, il passaggio ACK è riconoscere con [X + 1]. - citato dal Eddiecommento alla sua risposta.
smwikipedia,

14

Affinché la connessione funzioni, ciascuna parte deve verificare di poter inviare pacchetti all'altro lato. L'unico modo per essere sicuri di aver ricevuto un pacchetto dall'altra parte è quello di ottenere un pacchetto da essi che, per definizione, non sarebbe stato inviato se il pacchetto inviato non fosse passato . TCP utilizza essenzialmente due tipi di messaggi per questo: SYN (per richiedere la prova che questo pacchetto è passato) e ACK (che viene inviato solo dopo che un SYN è passato, per dimostrare che il SYN è riuscito). In realtà c'è un terzo tipo di messaggio, ma ci arriveremo tra un momento.

Prima che inizi la connessione, nessuna delle due parti sa davvero nulla dell'altra. Il client invia un pacchetto SYN al server per richiedere la prova che i suoi messaggi possono passare . Ciò non dice nulla a nessuno, ma è il primo passo della stretta di mano.

Se passa il SYN, allora il server sa che il client può inviargli pacchetti, perché, beh, è ​​appena successo. Ma ciò non dimostra che il server possa inviare i pacchetti indietro: i client possono inviare SYN per molte ragioni . Quindi il server deve rispedire due messaggi al client: un ACK (per dimostrare che il SYN è riuscito a passare) e un SYN (per richiedere un proprio ACK). TCP combina questi due messaggi in un unico messaggio SYN-ACK, se lo desideri, per ridurre il traffico di rete. Questo è il secondo passo della stretta di mano.

Poiché un SYN-ACK è un ACK, il client ora sa con certezza che può inviare pacchetti al server. E poiché un SYN-ACK è un SYN, sa anche che il server vuole la prova che questo messaggio è stato superato. Quindi restituisce un ACK: solo un semplice ACK questa volta, perché non ha più bisogno di prove che i suoi pacchetti possano passare. Questo è il passo finale della stretta di mano: il cliente ora sa che i pacchetti possono andare in entrambe le direzioni, e che il server è solo di conoscere questo numero (perché sa l'ACK passerà attraverso).

Una volta superato ACK, ora il server sa che può inviare pacchetti al client . Sa anche che il client lo sa, quindi può iniziare subito a inviare dati. La stretta di mano è completa. Abbiamo un buon canale.

Bene, a rigor di termini, non possiamo essere certi di avere un buon canale . Solo perché questa sequenza di pacchetti superata non garantisce rigorosamente che altri lo faranno. Non possiamo provarlo senza inviare un numero infinito di SYN e ACK, e quindi nient'altro sarebbe mai stato fatto, quindi questa non è davvero un'opzione pratica. Ma in pratica, tre passaggi risultano abbastanza buoni per la maggior parte degli scopi .


Questo non è vero: "un ACK (che viene inviato solo in risposta a SYN e quindi dimostra che il SYN ha superato)". Solo il primo pacchetto inviato da ciascuna estremità ha il flag SYN impostato e tutti i pacchetti diversi dal primo pacchetto dell'handshake a 3 vie hanno il flag ACK impostato. Il primo pacchetto non può ACK perché la seconda parte non ha ancora SINCRONIZZATO, ma ogni pacchetto dopo il primo deve ACK qualsiasi cosa sia già stata ricevuta dall'altra parte, indipendentemente dal fatto che i dati vengano rispediti o meno.
Monty Harder,

Grazie. Riformulazione: gli ACK vengono inviati una volta superato un SYN, anziché essere inviati solo in risposta ai SYN.
The Spooniest

Questa è la risposta migliore che può spiegare logicamente perché abbiamo persino bisogno del terzo messaggio. Grazie Spooniest.
Parth Patel

7

In realtà, una stretta di mano a 3 vie non è l'unico mezzo per stabilire una connessione TCP. È consentito anche lo scambio simultaneo di SYN: http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentProcessTheThreeWayHandsh-4.htm

Potrebbe essere visto come una sorta di doppia stretta di mano a 2 vie.


1
Un buon punto, tuttavia questo è molto raro poiché entrambi i dispositivi dovranno utilizzare la stessa porta di origine / destinazione ed entrambi i dispositivi dovranno inviare un SYN prima che l'altro riceva il SYN. Anche quando ciò accade, comporta l'invio di quattro pacchetti, che sono più dei tre pacchetti richiesti dalla tradizionale stretta di mano a 3 vie; in definitiva solo la possibilità di essere leggermente più veloce da impostare in termini di tempo complessivo a scapito di una minore efficienza complessiva (richiede la trasmissione del 33% in più di pacchetti).
Impara

4

La connessione TCP è bidirezionale. Ciò significa che in realtà è una coppia di connessioni unidirezionali. L'iniziatore invia SYN, il risponditore invia ACK: inizia una connessione simplex. "Quindi" il risponditore invia SYN, l'iniziatore invia ACK: inizia un'altra connessione simplex. Due connessioni simplex formano una sessione TCP duplex, d'accordo? Quindi logicamente ci sono quattro passaggi coinvolti; ma poiché i flag SYN e ACK sono diversi "campi" dell'intestazione TCP, possono essere impostati contemporaneamente: il secondo e il terzo passaggio (dei quattro) sono combinati, quindi tecnicamente ci sono tre scambi di pacchetti. Ogni connessione simplex (metà) utilizza lo scambio a 2 vie, come da te proposto.


2

Se Server e Client vogliono creare una connessione, devono confermare quattro cose:

  1. Il server deve confermare che può ricevere il pacchetto dal client
  2. Il cliente deve confermare che può ricevere il pacchetto dal server

  3. Il client deve confermare una cosa: il server può ricevere il pacchetto dal client

  4. Il server deve confermare una cosa: il client può ricevere il pacchetto dal server

Dopo Client ------SYN-----> Server, la regola 1 è confermata.

Successivamente Client <---ACK/SYN---- Server, le regole 2 e 3 sono confermate.

Quindi, è necessario un terzo pacchetto per confermare la regola 4.


1

Non è affatto necessario. È ovvio che un breve messaggio dovrebbe richiedere solo un pacchetto al server che include il messaggio start + e un pacchetto che lo riconosca.

Le risposte precedenti descrivono semplicemente il sistema senza discutere la necessità di numeri di sequenza casuali ecc. In primo luogo. La domanda originale riguardava la progettazione del TCP stesso: ovviamente se si utilizza il protocollo TCP, sono necessari tre messaggi perché quello è il protocollo. Ma perché TCP è stato progettato in questo modo in primo luogo?

Credo che l'idea originale fosse che non ci fosse distinzione tra client e server. Entrambi conoscevano i porti dell'altro in modo bidirezionale e potevano iniziare la conversazione. E questo ha richiesto Syns ecc.

Ma questo non è, ovviamente, come viene utilizzato oggi. Il server è in ascolto su una porta ben nota e lo fa e "accetta", il numero di porta del client è effimero. Non penso nemmeno che sia possibile per un server in attesa di un "accetta" di inviare una richiesta a un altro sullo stesso numero di porta client nei normali sistemi operativi.

(Si noti che si tratta dell'attivazione bidirezionale della connessione, che non viene mai eseguita oggi. Ciò è molto diverso dall'invio di messaggi bidirezionali tramite una connessione una volta stabilita.)

Per aggirare l'inefficienza TCP, utilizziamo protocolli come HTTP 1.1 che possono riutilizzare la stessa connessione per più richieste, evitando così l'handshake TCP che non era necessario in primo luogo.

Ma Http 1.1 è relativamente nuovo. E SSL / TLS necessitava di un modo per riutilizzare la sessione dall'inizio a causa del costo degli algoritmi PKI. Quindi quel protocollo include il proprio meccanismo di riutilizzo della sessione che viene eseguito su Http 1.1 che funziona su TCP.

Questo è il modo con il software. Fudges su kludges che, combinati, producono un risultato accettabile.


Tutto quanto sopra OSI layer 4 (ad esempio HTTP, FTP, ecc.) È esplicitamente fuori tema qui. Nei livelli da 1 a 4, non esiste client / server. TCP è una connessione tra peer. Sì, i protocolli di livello superiore creano una relazione client / server, ma qui è fuori tema.
Ron Maupin

1
A proposito, HTTP utilizza TCP, quindi l'handshake TCP è ancora necessario. Leggi il PROTOCOLLO DI CONTROLLO DELLA TRASMISSIONE RFC 793 per capire perché. Protocolli come HTTP richiedono che l'applicazione esegua il multiplexing che TCP farebbe normalmente per l'applicazione.
Ron Maupin

@RonMaupin La domanda originale era: perché? E la risposta è supportare un caso d'uso che non viene mai utilizzato in pratica dai livelli di livello superiore. Quindi, sembra abbastanza rilevante.
Montabile

@RonMaupin Sì, HTTP utilizza TCP. Che ho chiarito, grazie. Ma ciò non rende necessaria la stretta di mano TCP in alcun senso profondo.
Montabile

1
Le applicazioni e i protocolli a livello di applicazione sono esplicitamente fuori tema qui. @Eddie ha risposto alla domanda e se leggi e comprendi il TCP RFC, capirai perché l'handshake è necessaria. Non credo che aggiunga nulla per te per affermare, senza alcun supporto, che la stretta di mano non è necessaria, quando lo è chiaramente.
Ron Maupin

1

Dopo aver letto la risposta di Eddie (accettata come corretta), ci sono ancora dubbi sul perché il 1 ° host non può assegnare entrambi gli ISN con numeri casuali e il 2 ° semplicemente accettarlo. La vera ragione dell'uso della stretta di mano a 3 vie è quella di evitare le mezze connessioni . Scenario di metà connessione nell'handshake a 2 vie:
1) Client --- SYN -> Server
2) Il client cambia idea e non vuole più connettersi
3) Client <-X-ACK-- Server // ACK è stato perso
Il server non vede rinviato SYN, quindi pensa che il client abbia ottenuto il suo ACK e che la connessione sia stabilita. Di conseguenza il server ha una connessione che non verrà mai chiusa


In realtà, se un host (client e server è un concetto di applicazione di cui TCP non sa nulla) riceve un ACK o qualsiasi traffico su una connessione inesistente (passaggio 3 nello scenario), invierà un RST, non ignorerà il segmento ricevuto .
Ron Maupin

@RonMaupin Quindi ipotizziamo la situazione in cui il pacchetto ACK è stato perso.
Sanzhar Yeleuov,

Se l'ACK viene perso, la connessione avviata nel passaggio 1 scadrà. RFC 793 ha una spiegazione completa di tutti i tipi di scenari, inclusi i diagrammi.
Ron Maupin

@RonMaupin Voglio dire se lo scenario del mio post rimane lo stesso, l'unica cosa che è cambiata, che ACK è stato perso.
Sanzhar Yeleuov,

È tutto nella RFC. Fino a quando una connessione non è aperta, qualsiasi traffico ricevuto comporterà un RST. L'handshake a tre vie negozia i parametri di connessione, quindi il "server" non può inviare nulla al "client" ma è SYN / ACK fino a quando non riceve un ACK dal "client". Se il "server" SYN / ACK torna al "client" viene perso, il "server" tenterà di nuovo. La RFC spiega tutto questo.
Ron Maupin
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.