Warum brauchen wir einen 3-Wege-Handshake? Warum nicht einfach in beide Richtungen?

124

Der TCP-3-Wege-Handshake funktioniert folgendermaßen:

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

Warum nicht einfach das?

Client ------SYN-----> Server
Client <-----ACK------ Server
smwikipedia
quelle
24
Warum brauchen wir überhaupt einen Handschlag? Warum kann die Nachricht nicht mit dem ersten Paket gesendet werden?
Mehrdad
4
Wenn Sie den Handshake überspringen möchten, können Sie stattdessen UDP verwenden.
OzNetNerd
5
@Mehrdad, wenn Sie eine eigene Frage haben, verwenden Sie bitte den Link Frage stellen oben auf der Seite, um Ihre eigene Frage zu posten.
YLearn
40
@YLearn: Tut mir leid, es ist nicht wirklich eine Frage von mir, sondern diente dazu, die Leser zu motivieren, Antworten zu geben, die ein wenig tiefer gehen als in der Frage wörtlich gesagt.
Mehrdad
3
Vergessen Sie nicht TCP Fast Open (RFC 7413)
Alnitak

Antworten:

160

Teilen Sie den Handschlag in das auf, was er wirklich tut.

In TCP verfolgen die beiden Parteien mithilfe einer Sequenznummer, was sie gesendet haben. Im Endeffekt ist es eine laufende Byteanzahl von allem, was gesendet wurde. Der Empfänger kann die Sequenznummer des Gegners verwenden, um den Empfang zu bestätigen.

Die Sequenznummer beginnt jedoch nicht bei 0. Sie beginnt bei der ISN (Initial Sequence Number), die ein zufällig gewählter Wert ist. Und da TCP eine bidirektionale Kommunikation ist, können beide Parteien "sprechen", und daher müssen beide zufällig eine ISN als ihre Startsequenznummer erzeugen. Dies bedeutet wiederum, dass beide Parteien die andere Partei über ihre Start-ISN informieren müssen.

Am Ende haben Sie also diese Abfolge von Ereignissen, um eine TCP-Konversation zwischen Alice und Bob zu starten:

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]

Beachten Sie, dass vier Ereignisse eintreten:

  1. Alice wählt eine ISN und synchronisiert sie mit Bob.
  2. Bob BESTÄTIGT die ISN.
  3. Bob wählt eine ISN und synchronisiert sie mit Alice.
  4. Alice bestätigt die ISN.

Tatsächlich passieren die beiden mittleren Ereignisse (Nr. 2 und Nr. 3) im selben Paket. Was ein Paket zu einem SYNoder macht, ACKist einfach ein binäres Flag, das in jedem TCP-Header aktiviert oder deaktiviert ist , sodass nichts die Aktivierung dieser beiden Flags für dasselbe Paket verhindert. So endet der Drei-Wege-Handshake wie folgt:

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

Beachten Sie die beiden Instanzen von "SYN" und "ACK", jeweils eine in beide Richtungen.


Um auf Ihre Frage zurückzukommen, warum nicht einfach einen Zwei-Wege-Händedruck verwenden? Die kurze Antwort ist, dass ein Zwei-Wege-Handshake nur einer Partei erlauben würde, eine ISN einzurichten, und der anderen Partei, diese zu bestätigen. Dies bedeutet, dass nur eine Partei Daten senden kann.

TCP ist jedoch ein bidirektionales Kommunikationsprotokoll, dh, beide Seiten müssen Daten zuverlässig senden können. Beide Parteien müssen eine ISN einrichten, und beide Parteien müssen die ISN des anderen anerkennen.

In der Tat ist das, was Sie haben, genau Ihre Beschreibung des Zwei-Wege-Handshakes, aber in jede Richtung . Daher treten vier Ereignisse auf. Und wieder kommen die beiden mittleren Flags im selben Paket vor. Daher sind drei Pakete an einem vollständigen TCP-Verbindungsaufbauprozess beteiligt.

Eddie
quelle
6
Warum brauchen wir überhaupt ISNs? Menschen brauchen es nicht, warum Computer? Gibt es einen Beweis dafür oder haben wir sie nur, weil sie bequem sind?
Mehrdad
19
@Mehrdad: Sie benötigen Sequenznummern, damit Neuübertragungen ordnungsgemäß (oder überhaupt) funktionieren. Die ISN kann wegen Sequenzvorhersage-Angriffen nicht einfach Null sein .
Kevin
4
@Mehrdad Der Chatraum muss nicht unbedingt "Echtzeit" sein, wir können uns gegenseitig Nachrichten hinterlassen. Der Grund, warum ich es anderswo inszenieren wollte, ist, dass Sie jetzt eine andere Frage stellen. Das OP fragte "warum ist es ein 3-Wege-Handshake statt 2", aber jetzt fragen Sie "warum brauchen wir überhaupt Sequenznummern", was anders ist. Anstatt diesen Thread zu entgleisen, dachte ich, wir sollten die andere Frage im Chat diskutieren. Alternativ können Sie eine neue Frage stellen. Ich bin mir sicher, dass sie einige gute Antworten liefert.
Eddie
4
Tolle, prägnante Antwort. Das Lesen von "ACK SYN" fühlt sich grundsätzlich falsch an, aber Sie haben dies sogar mit +1 erklärt.
Lilienthal
3
Laut RFC 793, Transmission Control Protocol : " Der Hauptgrund für den Drei-Wege-Handshake besteht darin, zu verhindern, dass alte doppelte Verbindungsinitiationen zu Verwirrung führen. "
Ron Maupin
23

Der Drei-Wege - Handshake ist notwendig , da beide Parteien müssen syn chronize ihre Segmentfolgenummern bei ihrer Übertragung verwendet. Hierzu sendet jede von ihnen (wiederum) ein SYN - Segment mit einer Sequenznummer auf einen Zufallswert eingestellt n , die dann ack von der anderen Partei über ein ACK - Segment mit einer Sequenznummer auf nowledged n + 1 .

dr01
quelle
Warum wird die Bestätigung benötigt?
Paŭlo Ebermann
4
@ PaŭloEbermann: Weil der Server sonst keine Ahnung hat, ob der Client jemals das SYN erhalten hat, und es wichtig ist, dass der Client das erhält.
Mooing Duck
2
@ PaŭloEbermann Und um es zu beweisen, muss der ACK-Schritt mit [X + 1] quittieren. - Zitiert aus Eddiedem Kommentar zu seiner Antwort.
smwikipedia
14

Damit die Verbindung funktioniert, muss jede Seite sicherstellen, dass sie Pakete an die andere Seite senden kann. Der einzige Weg, um sicherzugehen, dass Sie ein Paket auf die andere Seite erhalten, besteht darin, ein Paket von ihnen zu erhalten, das per Definition nicht gesendet worden wäre, wenn das von Ihnen gesendete Paket nicht durchgekommen wäre . TCP verwendet dazu im Wesentlichen zwei Arten von Nachrichten: SYN (um den Beweis anzufordern, dass dieses Paket durchgekommen ist) und ACK (das nur gesendet wird, nachdem ein SYN durchgekommen ist, um zu beweisen, dass das SYN durchgekommen ist). Es gibt tatsächlich eine dritte Art von Botschaft, aber wir werden gleich darauf eingehen.

Bevor die Verbindung hergestellt wird, weiß keine Seite wirklich etwas über die andere. Der Client sendet ein SYN-Paket an den Server, um den Nachweis anzufordern, dass seine Nachrichten durchkommen können . Das sagt keiner der beiden Personen etwas, aber es ist der erste Schritt des Handshakes.

Wenn der SYN durchkommt, weiß der Server, dass der Client Pakete an ihn senden kann, weil es einfach passiert ist. Dies beweist jedoch nicht, dass der Server Pakete zurücksenden kann: Clients können aus vielen Gründen SYNs senden . Der Server muss also zwei Nachrichten an den Client zurücksenden: eine ACK (um zu beweisen, dass die SYN durchgekommen ist) und eine SYN (um eine eigene ACK anzufordern). TCP kombiniert diese beiden Nachrichten zu einer SYN-ACK-Nachricht, um den Netzwerkverkehr zu reduzieren. Dies ist der zweite Schritt des Handshakes.

Da ein SYN-ACK ein ACK ist, weiß der Client jetzt genau, dass er Pakete an den Server senden kann. Und da ein SYN-ACK ein SYN ist, möchte der Server auch nachweisen, dass diese Nachricht eingegangen ist. Also sendet es eine ACK zurück: diesmal nur eine einfache ACK, da es keinen Beweis mehr braucht, dass seine Pakete durchkommen können. Dies ist der letzte Schritt des Handshakes: Der Client weiß nun, dass Pakete in beide Richtungen gesendet werden können und dass der Server dies gerade herausfinden wird (da er weiß, dass die ACK durchlaufen wird).

Sobald diese ACK durch ist, weiß der Server, dass er Pakete an den Client senden kann . Es weiß auch, dass der Client dies weiß, sodass er sofort mit dem Senden von Daten beginnen kann. Der Handschlag ist abgeschlossen. Wir haben einen guten Kanal.

Genau genommen können wir nicht sicher sein, ob wir einen guten Kanal haben . Nur weil diese Folge von Paketen bekam nicht durch nicht streng garantieren , dass andere werden. Wir können das nicht beweisen, ohne eine unendliche Anzahl von SYNs und ACKs zu senden, und dann würde nie etwas anderes getan werden. Das ist also keine wirklich praktische Option. In der Praxis erweisen sich jedoch drei Schritte für die meisten Zwecke als ausreichend .

Der Löffeligste
quelle
Das ist falsch: "Ein ACK (der nur als Antwort auf SYNs gesendet wird und somit beweist, dass das SYN durchgekommen ist)." Nur für das erste von jedem Ende gesendete Paket ist das SYN-Flag gesetzt, und für alle Pakete mit Ausnahme des allerersten Pakets des 3-Wege-Handshakes ist das ACK-Flag gesetzt. Das erste Paket kann nicht ACK, da der zweite Teilnehmer noch nicht SYNED ist, aber jedes Paket nach dem ersten muss ACK, was auch immer bereits vom anderen Ende empfangen wurde, unabhängig davon, ob Daten zurückgesendet werden oder nicht.
Monty Harder
Vielen Dank. Umformulierung: ACKs werden gesendet, sobald eine SYN abgeschlossen ist, anstatt nur als Antwort auf SYNs gesendet zu werden.
The Spooniest
Dies ist die beste Antwort, die logisch erklären kann, warum wir sogar die dritte Nachricht benötigen. Danke, Spooniest.
Parth Patel
7

Tatsächlich ist ein 3-Wege-Handshake nicht das einzige Mittel, um eine TCP-Verbindung herzustellen. Ein gleichzeitiger SYN-Austausch ist ebenfalls zulässig: http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentProcessTheThreeWayHandsh-4.htm

Das könnte als eine Art doppelter Zwei-Wege-Handschlag angesehen werden.

Lexelby
quelle
1
Ein guter Punkt, dies ist jedoch sehr selten, da beide Geräte denselben Quell- / Zielport verwenden müssen und beide Geräte eine SYN senden müssen, bevor der andere das SYN empfängt. Selbst wenn dies der Fall ist, werden vier Pakete gesendet. Dies sind mehr als die drei Pakete, die beim herkömmlichen 3-Wege-Handshake erforderlich sind. letztendlich nur die Möglichkeit, sich in Bezug auf die Gesamtzeit auf Kosten einer geringeren Gesamteffizienz etwas schneller einzurichten (es müssen 33% mehr Pakete übertragen werden).
YLearn
4

Die TCP-Verbindung ist bidirektional. Dies bedeutet, dass es sich tatsächlich um ein Paar Einwegverbindungen handelt. Der Initiator sendet SYN, der Responder sendet ACK: Eine Simplex-Verbindung beginnt. "Dann" sendet der Responder SYN, der Initiator sendet ACK: Eine weitere Simplex-Verbindung beginnt. Zwei Simplex-Verbindungen bilden eine Duplex-TCP-Sitzung. Es sind also logischerweise vier Schritte erforderlich. Da jedoch SYN- und ACK-Flags unterschiedliche "Felder" des TCP-Headers sind, können sie gleichzeitig gesetzt werden - der zweite und der dritte Schritt (von den vier) werden kombiniert, so dass es technisch gesehen drei Paketaustausche gibt. Wie Sie vorgeschlagen haben, verwendet jede Simplex- (Halb-) Verbindung einen 2-Wege-Austausch.

Sergio
quelle
2

Wenn Server und Client eine Verbindung herstellen möchten, müssen sie vier Dinge bestätigen:

  1. Der Server muss bestätigen, dass er ein Paket vom Client empfangen kann
  2. Der Client muss bestätigen, dass er ein Paket vom Server empfangen kann

  3. Der Client muss eine Sache bestätigen: Der Server kann ein Paket vom Client empfangen

  4. Der Server muss eine Sache bestätigen: Der Client kann ein Paket vom Server empfangen

Danach Client ------SYN-----> Serverwird Regel 1 bestätigt.

Danach Client <---ACK/SYN---- Serverwerden Regel 2 und 3 bestätigt.

Es wird also ein drittes Paket benötigt, um Regel 4 zu bestätigen.

codeman-cs ist meine Github-ID
quelle
1

Es ist überhaupt nicht notwendig. Es ist offensichtlich, dass für eine Kurznachricht nur ein Paket an den Server erforderlich sein sollte, das die Start + -Nachricht enthält, und ein Paket, das sie zurückbestätigt.

Die vorherigen Antworten beschreiben lediglich das System, ohne dass zunächst auf die Notwendigkeit von Zufallsfolgenummern usw. eingegangen wird. Die ursprüngliche Frage betraf den Entwurf von TCP selbst. Wenn Sie das TCP-Protokoll verwenden, benötigen Sie offensichtlich drei Nachrichten, da dies das Protokoll ist. Aber warum wurde TCP überhaupt so konzipiert?

Ich glaube, die ursprüngliche Idee war, dass es keinen Unterschied zwischen Clients und Servern gab. Beide kannten die Ports des anderen bidirektional und konnten das Gespräch beginnen. Und das erforderte Syns etc.

Aber das ist natürlich nicht so, wie es heute verwendet wird. Der Server lauscht an einem bekannten Port und "akzeptiert", die Client-Portnummer ist kurzlebig. Ich denke nicht einmal, dass es möglich ist, dass ein Server, der auf ein "Annehmen" wartet, unter normalen Betriebssystemen eine Anfrage an einen anderen über dieselbe Client-Portnummer sendet .

(Beachten Sie, dass es sich um eine bidirektionale Initiierung der Verbindung handelt, die heute noch nie erfolgt ist. Dies unterscheidet sich erheblich vom Senden bidirektionaler Nachrichten über eine einmal hergestellte Verbindung.)

Um die TCP-Ineffizienz zu umgehen, verwenden wir Protokolle wie HTTP 1.1, mit denen dieselbe Verbindung für mehrere Anforderungen wiederverwendet werden kann, und vermeiden so das TCP-Handshake, das ursprünglich nicht erforderlich war.

Aber HTTP 1.1 ist relativ neu. Und SSL / TLS brauchte aufgrund der Kosten für die PKI-Algorithmen eine Möglichkeit, die Sitzung von Anfang an wiederzuverwenden. Daher enthält dieses Protokoll einen eigenen Mechanismus zur Wiederverwendung von Sitzungen, der auf HTTP 1.1 und TCP ausgeführt wird.

So ist der Weg mit Software. Fudges auf Kludges, die zusammen ein akzeptables Ergebnis liefern.

Tuntable
quelle
Alles, was über der OSI-Ebene 4 liegt (z. B. HTTP, FTP usw.), ist hier ausdrücklich nicht zum Thema. In den Schichten 1 bis 4 gibt es keinen Client / Server. TCP ist eine Verbindung zwischen Peers. Ja, Protokolle der oberen Schicht stellen eine Client / Server-Beziehung her, aber das ist hier nicht thematisch.
Ron Maupin
1
Übrigens verwendet HTTP TCP, sodass der TCP-Handshake weiterhin erforderlich ist. Lesen Sie das RFC 793 TRANSMISSION CONTROL PROTOKOLL, um zu verstehen, warum. Bei Protokollen wie HTTP muss die Anwendung das Multiplexing ausführen, das TCP normalerweise für die Anwendung ausführen würde.
Ron Maupin
@ RonMaupin Die ursprüngliche Frage war, warum? Die Antwort ist, einen Anwendungsfall zu unterstützen, der in der Praxis von den Schichten der oberen Ebene nie verwendet wird. Scheint also ziemlich relevant zu sein.
Tuntable
@ RonMaupin Ja, HTTP verwendet TCP. Was ich geklärt habe, danke. Dies macht den TCP-Handshake jedoch in keiner Weise notwendig.
Tuntable
1
Die Anwendungen und Protokolle der Anwendungsschicht sind hier ausdrücklich nicht zum Thema. @ Eddie beantwortete die Frage, und wenn Sie den TCP-RFC lesen und verstehen, werden Sie erfahren, warum der Handshake erforderlich ist. Ich glaube nicht, dass es etwas hinzufügt, wenn Sie ohne jegliche Unterstützung behaupten, dass der Handschlag nicht notwendig ist, wenn er eindeutig ist.
Ron Maupin
1

Nach dem Lesen der Antwort von Eddie (als korrekt akzeptiert) gibt es immer noch die Frage, warum der 1. Host nicht beide ISNs mit Zufallszahlen zuweisen kann und der 2. einfach akzeptieren kann. Ein echter Grund für die Verwendung von 3-Wege-Handshakes ist die Vermeidung von Halbverbindungen . Halbes Verbindungsszenario im 2-Wege-Handshake:
1) Client --- SYN -> Server
2) Client hat seine Meinung geändert und möchte keine Verbindung mehr herstellen
3) Client <-X-ACK-- Server // ACK ging verloren
Der Server kann SYN nicht erneut senden. Daher glaubt er, dass der Client seine ACK erhalten hat und die Verbindung hergestellt wurde. Infolgedessen hat der Server eine Verbindung, die niemals geschlossen wird

Sanzhar Yeleuov
quelle
Wenn ein Host (Clients und Server sind ein Anwendungskonzept, von dem TCP nichts weiß) eine ACK oder Datenverkehr über eine nicht vorhandene Verbindung empfängt (Schritt 3 in Ihrem Szenario), sendet er eine RST und ignoriert das empfangene Segment nicht .
Ron Maupin
@RonMaupin Dann nehmen wir an, dass das ACK-Paket verloren gegangen ist.
Sanzhar Yeleuov
Wenn die ACK verloren geht, läuft die in Schritt 1 initiierte Verbindung ab. RFC 793 enthält eine vollständige Erläuterung aller Arten von Szenarien, einschließlich Diagrammen.
Ron Maupin
@ RonMaupin Ich meine, wenn das Szenario von meinem Post gleich bleibt, hat sich nur geändert, dass ACK verloren gegangen ist.
Sanzhar Yeleuov
Es ist alles in der RFC. Bis eine Verbindung hergestellt ist, führt der empfangene Datenverkehr zu einer RST. Der Drei-Wege-Handshake handelt die Verbindungsparameter aus, sodass der "Server" nichts an den "Client" zurücksenden kann, sondern nur SYN / ACK, bis er eine ACK vom "Client" erhält. Wenn der "Server" SYN / ACK zurück zum "Client" verloren geht, versucht der "Server" es erneut. Der RFC erklärt das alles.
Ron Maupin