Transmission Control Protocol
TCP (Transmission Control Protocol) ist ein Netzwerkprotokoll, das definiert, auf welche Art und Weise Daten zwischen Netzwerkkomponenten ausgetauscht werden sollen.
TCP (Transmission Control Protocol) | |
---|---|
Familie: | Internetprotokollfamilie |
Einsatzgebiet: | Zuverlässiger bidirektionaler Datentransport |
Netzwerk-IP-Transportprotokoll: | Hypertext Transfer Protocol (HTTP), Simple Mail Transfer Protocol (SMTP) |
Standards: | RFC 793 (1981) RFC 7323 (2014) |
= Beschreibung = == Geschichte ==
- Entwickelt von Robert E. Kahn und Vinton G. Cerf als Forschungsarbeit.
- Beginn 1973, erste Standardisierung 1981 als RFC 793.
- Danach gab es viele Erweiterungen, diese werden bis heute in RFCs spezifiziert.
== Was ist TCP ==
- Ist ein zuverlässiges, verbindungsorientiertes, paketvermitteltes (nicht paketvermittelnd) Transportprotokoll.
- TCP ermöglicht die Übertragung eines Datenstroms.
- Im Unterschied zum verbindungslosen User Datagram Protokoll (UDP) stellt TCP eine Verbindung zwischen zwei Endpunkten (Sockets) einer Netzverbindung her.
- Auf dieser Verbindung können in beide Richtungen Daten übertragen werden.
== Vorteile ==
- Netzwerküberlastungskontrolle.
- Zuverlässige Datenübertragung:
- erkennt verlorene Segmente, doppelte Segmente und fehlerhafte Segmente.
== Allgemeines == TCP ist im Prinzip eine Ende-zu-Ende-Verbindung in Vollduplex.
- Kann auch als zwei Halbduplexverbindungen betrachtet werden (Informationsfluss in beide Richtungen (allerdings nicht gleichzeitig)).
- Die Daten in Gegenrichtung können zusätzliche Steuerungsinformationen enthalten.
- Anwendungen, die TCP häufig nutzen, sind zum Beispiel Webbrowser und Webserver.
=== TCP-Software ===
- Übernimmt Verbindungsverwaltung sowie die Datenübertragung.
- Netz-Protokollstack des Betriebssystems.
- Anwendungsprogramme nutzen Sockets.
=== Software-Schnitstelle ===
- bei Windows in extra einzubindenden Programmbibliotheken („Winsock.dll“ bzw. „wsock32.dll“).
- Linux und andere unixoide Betriebssysteme enthalten einen Socketlayer im Betriebssystemkern (Zugriff über Systemaufrufe).
== TCP-Verbindung ==
- Jede TCP-Verbindung wird eindeutig durch zwei Endpunkte identifiziert.
- Ein Endpunkt stellt ein geordnetes Paar dar (IP-Adresse und Port).
- Ein solches Paar bildet eine bidirektionale Software-Schnittstelle (Socket).
TCP-Verbindungen werden durch vier Werte (einem Quadrupel) eindeutig identifiziert: (Quell-IP-Adresse, Quell-Port, Ziel-IP-Adresse, Ziel-Port) === Beispiel === #Ein Serverprozess erzeugt einen Socket auf Port 80 (bind). #*Markiert diesen für eingehende Verbindungen (listen). #*Fordert vom Betriebssystem die nächste anstehende Verbindung an (accept). #*Diese Anforderung blockiert den Serverprozess zunächst, da noch keine Verbindung existiert. #Die erste Verbindungsanfrage kommt und wird vom Betriebssystem angenommen, die Verbindung kommt zustande. #Jetzt wird diese Verbindung durch das Quadrupel identifiziert. ##Der Serverprozess wird aufgeweckt und ihm ein Handle für diese Verbindung überreicht. ##Üblich startet der Serverprozess einen Kindprozess, dem er die Behandlung der Verbindung delegiert. ##Der Serverprozess fährt mit einer weiterer Accept-Anforderung an das Betriebssystem fort.
- Dadurch ist es möglich, dass ein Webserver mehrere Verbindungen von verschiedenen Rechnern annehmen kann.
=== Ports ===
- Portnummern sind Dualsystem 16-Bit-Zahlen und reichen von 0 bis 65535.
- Ports von 0 bis 1023 sind reserviert
- Vergeben von Internet Assigned Numbers Authority (IANA)
- z.B. ist Port 80 für Hypertext Transfer Protocol (HTTP) reserviert.
- Das Benutzen der vordefinierten Ports ist nicht bindend.
- Jeder Administrator kann bspw. einen FTP-Server (normalerweise Port 21) auch auf einem beliebigen Port laufen lassen.
- Mehrfaches listen auf demselben Port ist nicht möglich.
= Header = === Allgemeines ===
- Das TCP-Segment besteht immer aus zwei Teilen: dem Header und der Nutzlast.
- Die Nutzlast enthält die zu übertragenden Daten.
- Die wiederum Protokollinformationen der Anwendungsschicht, wie HTTP oder FTP, entsprechen können.
- Der Header enthält für die Steuerung der Kommunikation erforderliche Daten.
- Da das Options-Feld in der Regel nicht genutzt wird, hat ein typischer Header eine Größe von 20 Byte.
=== Felder des TCP-Header ===
Feld | Funktion | Größe |
---|---|---|
Source Port (Quellport) |
|
2 Byte |
Destinations Port (Zielport) |
|
2 Byte |
Sequence Number |
|
4 Byte |
Acknowledgement Number |
|
4 Byte |
Data Offset |
|
4 Bit |
Reserved |
|
4 Bit |
Control-Flags |
|
8 Bit |
(Receive) Window |
|
2 Byte |
Checksum |
|
2 Byte |
Urgent Pointer |
|
2 Byte |
Options |
|
0–40 Byte |
=== TCP-Flags ===
Feld | Funktion | Größe |
---|---|---|
ECE-Flag (ECN-Echo) |
|
1 Bit |
CRW-Flag (Congestion Window Reduced) |
|
1 Bit |
URG-Flag (Urgent) |
|
1 Bit |
ACK-Flag (Acknowledgment) |
|
1 Bit |
PSH-Flag (Push) |
|
1 Bit |
RST-Flag (Reset) |
|
1 Bit |
SYN-Flag (Synchronize) |
|
1 Bit |
FIN-Flag (Finish) |
|
1 Bit |
= Installation = = Syntax = == Parameter == == Optionen == = Konfiguration = == Dateien == = Anwendungen = == Verbindungsaufbau und -abbau == === Allgemein === Ein Server, der seinen Dienst anbietet, erzeugt einen Endpunkt (Socket) mit der Portnummer und seiner IP-Adresse.
- Bezeichnet als "passive open" oder "listen".
Ein Client, der eine Verbindung aufbauen will, erzeugt einen Endpunkt (Socket) mit seiner IP-Adresse und einer eigenen, noch freien Portnummer.
- Mit der Adresse des Servers und dem Port kann dann eine Verbindung aufgebaut werden.
Während der Datenübertragungsphase sind die Rollen von Client und Server (aus TCP-Sicht) vollkommen symmetrisch.
- Bezeichnet als "active open"
Jeder der beiden beteiligten Rechner einen Verbindungsabbau einleiten. === Verbindungsaufbau ===
#Der Client sendet dem Server ein SYN-Paket mit einer Sequenznummer x. #*Die Sequenznummern sind für die Sicherstellung einer vollständigen Übertragung in der richtigen Reihenfolge und ohne Duplikate wichtig. #*Ein Paket, dessen SYN-Bit im Header gesetzt ist. #*Die Start-Sequenznummer ist eine beliebige zufällige Zahl, abhängig von der TCP-Implementierung. #Der Server empfängt das Paket und antwortet. #*Port geschlossen, antwortet er mit einem TCP-RST, ein Signal, dass keine Verbindung aufgebaut werden kann. #*Port geöffnet, bestätigt er den Erhalt des ersten SYN-Pakets und stimmt dem Verbindungsaufbau zu, indem er ein SYN/ACK-Paket zurückschickt. #**Ein Paket, mit ACK-Flag im TCP-Header, welche die Sequenznummer x+1 des SYN-Pakets im Header enthält. #**Der Server sendet im Gegenzug seine Start-Sequenznummer y, diese ist unabhängig von der Start-Sequenznummer des Clients. #Der Client bestätigt den Erhalt des SYN/ACK-Pakets durch ein eigenes ACK-Pakets mit der Sequenznummer x+1. #*Wird auch als „Forward Acknowledgement“ bezeichnet. #*Aus Sicherheitsgründen sendet der Client die Sequenznummer des Servers + 1 im ACK-Segment zurück. #Die Verbindung ist damit aufgebaut. ==== Verbindungsaufbau Beispiel ====
1. | SYN-SENT | → | <SEQ=100><CTL=SYN> | → | SYN-RECEIVED |
2. | SYN/ACK-RECEIVED | ← | <SEQ=300><ACK=101><CTL=SYN,ACK> | ← | SYN/ACK-SENT |
3. | ACK-SENT | → | <SEQ=101><ACK=301><CTL=ACK> | → | ESTABLISHED |
- Nach Aufbau ist die Verbindung für beide Kommunikationspartner gleichberechtigt
- Man kann einer bestehenden Verbindung auf TCP-Ebene nicht ansehen, wer der Server und wer der Client ist.
- Eine Unterscheidung dieser beiden Rollen in der weiteren Betrachtung keine Bedeutung mehr.
=== Verbindungsabbau ===
- Der Verbindungsabbau kann beidseitig oder schrittweise einseitig erfolgen.
- Der geregelte Verbindungsabbau erfolgt dem Verbindungsaufbau ähnlich.
- #Statt dem SYN-Bits kommt das FIN-Bit zum Einsatz, welches anzeigt, dass keine Daten mehr vom Sender kommen werden.
- #Der Erhalt des Pakets wird mit ACK bestätigt und der Empfänger des FIN-Pakets sendet zuletzt seinerseits ein FIN-Paket.
- #Dieses FIN-Paket wird ihm zuletzt bestätigt.
- Ein verkürztes ist Verfahren möglich, bei dem FIN und ACK genau wie beim Verbindungsaufbau im selben Paket untergebracht werden.
=== Halb geschlossene Verbindungen ===
- Der Verbindungsabbau erfolgt schrittweise einseitig.
- Erlaubt der Gegenseite nach der einseitigen Trennung noch Daten zu übertragen.
=== Halb offene Verbindungen ===
- wenn eine Seite abstürzt, ohne dass die verbleibende Seite dies erfährt.
- Effekt: Betriebssystemressourcen werden nicht freigegeben.
- Ursprung: TCP-Verbindungen von der Protokollseite bestehen, bis sie abgebaut werden.
==== Maximum segment lifetime (MSL)====
- Die maximale Zeit, die ein Segment im Netzwerk verbringen kann, bevor es verworfen wird.
- Nach dem Senden des letzten ACKs wechselt der Client in einen zwei MSL andauernden Wartezustand (wait state), in dem alle verspäteten Segmente verworfen werden.
- Dadurch wird sichergestellt, dass keine verspäteten Segmente als Teil einer neuen Verbindung fehlinterpretiert werden können.
- Außerdem wird eine korrekte Verbindungsterminierung sichergestellt.
- Geht ACK y+1 verloren, läuft beim Server der Timer ab, und das LAST_ACK-Segment wird erneut übertragen.
=== Puffer ===
- Beim Datenversand über TCP werden zwei Puffer verwendet.
#Senderseitig übermittelt die Applikation die Sendedaten an TCP und dieses puffert die Daten. #Effizient werden mehrere kleine Übertragungen in Form einer einzigen großen gesendet. #Empfängerseitig landen die empfangenen Daten im Puffer, dieser verfolgt ähnliche Ziele.
- Wenn von TCP mehrere einzelne Pakete empfangen wurden, ist es besser, diese zusammengefügt an die Applikation weiterzugeben.
=== Drei-Wege-Handschlag ===
- Typisch werden Antworten auf das erste SYN- bzw. FIN-Paket zu einem einzelnen Paket zusammengefasst (SYN/ACK bzw. FIN/ACK).
- Theoretisch wäre auch das Versenden zweier separater Pakete denkbar.
- In diesem Fall müssen nur noch drei Pakete versendet werden, man spricht vom Drei-Wege-Handschlag.
- Das Zusammenfassen des FIN-Pakets und ACK-Pakets ist problematisch.
- Das Fin-Paket signalisiert „keine weiteren Daten“.
- Allerdings kann der Sender des FIN-Pakets weiterhin Daten empfangen wollen (halb geschlossenen Verbindung).
; Überlegung #Den Beginn einer HTTP-Anfrage im SYN-Paket mitschicken, weitere Daten nach Verbindungsaufbau. #Im letzten HTTP-Request-Paket die Verbindung mittels FIN schließen.
- In der Praxis nicht angewendet da:
- Wenn der Browser die Verbindung auf diese Art schließt, würde möglicherweise der Server die Verbindung schließen, anstatt die Anfrage vollständig zu beantworten.
== Datenübertragung ==
=== TCP-/IP-Segment-Größe ===
- Typischerweise eine Größe von maximal 1500Bytes .
- Muss in die darunter liegende Übertragungsschicht passen, das Internetprotokoll (IP).
- IP-Pakete sind zwar bis 65.535Bytes (64KiB) spezifiziert, werden aber meist über Ethernet übertragen.
- Bei Ethernet ist die Größe der (Layer-3-)Nutzdaten auf 64 bis 1500Bytes festgelegt (bei Jumbo Frames höher).
- TCP- und IP-Protokoll definieren jeweils einen Header von 20Bytes Größe.
- Für die (Applikations-)Nutzdaten bleiben in einem TCP/IP-Paket also 1460Bytes übrig.
- Da die meisten Internet-Anschlüsse DSL verwenden, kommt zusätzlich das Point-to-Point Protocol (PPP) zwischen IP und Ethernet zur Anwendung (8Bytes).
Die Nutzdaten reduzieren sich also auf insgesamt 1500− 20− 20− 8 =1452Bytes Maximum Segment Size (MSS).
- Dies entspricht einer maximalen Nutzdatenrate von 96,8 %.
=== Aufteilen der Anwendungsdaten auf TCP-/IP-Segmente === # Empfänger und Sender einigen sich vor dem Datenaustausch über das Options-Feld auf die Größe der Maximum Segment Size (MSS). # Als Beispiel legt ein Webserver einen 7Kilobyte großen Datenblock im Puffer ab. #* Um mit einem 1460Byte großen Nutzdatenfeld 7Kilobyte Daten zu versenden: #*# Teilt die TCP-Software die Daten auf mehrere Pakete auf #*# Fügt einen TCP-Header hinzu und versendet die TCP-Segmente. #* Dieser Vorgang wird Segmentierung genannt. # Der Datenblock im Puffer wird in fünf Segmente aufgeteilt, diese werden nacheinander abgeschickt. ## Jedes Segment erhält durch die TCP-Software einen TCP-Header. # Segmente kommen nicht zwingend in richtiger Reihenfolge an. # Um die Segmente wieder zu sortieren, ist jedes Segment nummeriert. #* Bei der Zuordnung der Segmente im Empfänger wird die Sequenznummer herangezogen. #Die TCP-Software des Empfängers bestätigt die einwandfrei angekommenen TCP-Segmente. #*Andernfalls werden die Pakete neu angefordert. === Beispiel einer TCP-/IP-Datenübertragung ===
#Der Sender schickt sein erstes TCP-Segment mit einer Sequenznummer SEQ=1 und einer Nutzdatenlänge von 1460Bytes an den Empfänger. #Der Empfänger bestätigt es mit einem TCP-Header, ohne Daten, mit ACK=1461 und fordert das zweite TCP-Segment ab dem Byte Nummer 1461 an. #Sender schickt es dann mit einem TCP-Segment und SEQ=1461 an den Empfänger. #Empfäner bestätigt es wieder mit einem ACK=2921.
- Der Empfänger braucht nicht jedes TCP-Segment zu bestätigen, wenn diese zusammenhängend sind.
- Empfängt er die TCP-Segmente 1–5, so braucht er nur das letzte TCP-Segment zu bestätigen.
- Fehlt zum Beispiel das 3. Segment, kann er nur die 1 und die 2 bestätigen, 4 und 5 jedoch noch nicht.
- Da der Sender keine Bestätigung für die 3 bekommt, läuft sein Timer ab, und er verschickt die 3 noch einmal.
- Kommt die 3 beim Empfänger an, so bestätigt er alle fünf TCP-Segmente, wenn beide die TCP-Option Selective ACK (SACK) unterstützen.
- Der Sender startet für jedes TCP-Segment, welches er auf die Reise schickt, einen Retransmission Timer.
=== Retransmission Timer ===
- Zur Feststellung, wann ein Paket im Netzwerk verloren gegangen ist, wird vom Sender ein Timeout verwendet, bis zu dem das ACK der Gegenseite eingetroffen sein muss.
- Timeout zu niedrig, Pakete werden doppelt geschickt.
- Timeout zu hoch, velorene Pakete werden zu spät neu geschickt.
- Aufgrund unterschiedlicher Laufzeiten der IP-Pakete ist nur ein dynamischer Timer sinnvoll.
=== Zusammenhang von Flusssteuerung und Staukontrolle === In den folgenden zwei Abschnitten werden die TCP-Konzepte zur Flusssteuerung und Staukontrolle (oder Überlaststeuerung) erläutert.
- Dabei werden das Sliding Window und das Congestion Window eingeführt.
- Der Sender wählt als tatsächliche Sendefenstergröße das Minimum aus beiden Fenstern.
- Es werden ARQ-Protokolle (Automatic Repeat reQuest) für eine zuverlässige Datenübertragung eingesetzt.
=== Flusssteuerung ===
Da Daten aus dem Puffer gelesen werden, ändert sich der Füllstand des Puffers ständig.
- Deshalb ist es notwendig, den Datenfluss dem Füllstand entsprechend zu steuern.
- Dies geschieht mit dem Sliding Window und dessen Größe.
- Der Puffer des Senders wird auf auf 10 Segmente erweitert.
;Im Sliding Window (a) werden gerade die Segmente 1–5 übertragen. # Obwohl der Puffer voll ist, werden die nächsten Daten (ab Byte 7301) mit ACK=7301 angefordert. #* Das nächste Segment kann nicht mehr verarbeitet werden. #* Mit dem Window-Feld (=0) teilt er dem Sender mit, dass keine Daten mehr verschickt werden sollen. # Die Anwendung liest die Segmente 1–5 aus dem Puffer, es werden 7300Byte frei. # Er kann die restlichen Segmente 6–10 mit einem TCP-Header (SEQ=1, ACK=7301, Window=7300), beim Sender anfordern. # Der Sender weiß nun, dass er maximal fünf Segmente schicken kann, und verschiebt das Window um fünf Segmente nach rechts (Sliding Window (b)). # Die Segmente 6–10 werden nun alle zusammen als Burst verschickt. # Beim Ankommen aller TCP-Segmente beim Empfänger, quittiert er sie (SEQ=1 und ACK=14601) und fordert die nächsten Daten an. === Überlaststeuerung/Staukontrolle (Congestion Control) ===
- Wird eine Verbindung stark belastet, werden immer mehr Pakete verworfen.
- Durch die Wiederholung steigt wiederum die Belastung, dies sorgt (ohne Maßnahmen) für einen Datenstau.
- Die Verlustrate wird von einem IP-Netzwerk ständig beobachtet.
- Normalerweise wird eine TCP/IP-Verbindung langsam gestartet (Slow-Start) und die Senderate schrittweise erhöht, bis zum Datenverlust.
- Ein Datenverlust verringert die Senderate, ohne Verlust wird sie wiederum erhöht.
==== Algorithmus zur Überlaststeuerung ==== Gehen bei einer bestimmten Fenstergröße Pakete verloren, kann das festgestellt werden, wenn der Sender innerhalb einer bestimmten Zeit (Timeout) kein ACK erhält.
- Man muss davon ausgehen, dass das Paket aufgrund zu hoher Netzlast von einem Router im Netz verworfen wurde (Stau im Netz).
- Um den Stau aufzulösen, müssen alle beteiligten Sender ihre Netzlast reduzieren.
Dazu werden im RFC 2581 vier Algorithmen definiert: #slow start #congestion avoidance #fast retransmit #fast recovery,
- slow start und congestion avoidance werden zusammen verwendet.
- fast retransmit und fast recovery werden zusammen verwendet, sind eine Erweiterung von slow start und congestion avoidance.
==== Slow Start Slow Start und Congestion Avoidance ====
- Der Slow-Start-Algorithmus dient zur Bestimmung des congestion window.
- Da die momentane Auslastung des Netzes nicht bekannt ist, wird mit kleinen Datenmengen begonnen.
#Der Algorithmus startet mit einem kleinen Fenster, von einer Maximum Segment Size (MSS), in dem Datenpakete vom Sender zum Empfänger übertragen werden. #Der Empfänger sendet ACK an den Sender zurück. #Für jedes empfangene ACK wird die Größe des congestion window um eine MSS erhöht. #*Dies führt innerhalb einer Roundtrip-Zeit zu einer Verdopplung des Congestion Windows. #Dieses exponentielle Wachstum wird so lange fortgesetzt, bis der Slow-Start Threshold erreicht wird. #*Die Phase des exponentiellen Wachstums wird auch Slow Start Phase genannt. #Danach wird das Congestion Window nur noch um eine MSS erhöht, wenn alle Pakete aus dem Fenster erfolgreich übertragen wurden. #*Es wächst pro Roundtrip-Zeit nur noch um eine MSS, also nur noch linear. #**Diese Phase wird als Congestion Avoidance Phase bezeichnet. #*Das Wachstum wird beendet, wenn das vom Empfänger festgelegte Empfangsfenster erreicht worden ist. Kommt es zu einem Timeout, wird das congestion window auf 1 zurückgesetzt, der slow-start threshold wird auf die Hälfte der gesendeten, unquittierten Pakete herabgesetzt (Flight Size).
- Die Phase des exponentiellen Wachstums wird also verkürzt.
- Das Fenster wächst bei häufigen Paketverlusten nur langsam.
==== Fast-Retransmit und Fast-Recovery ====
- Werden eingesetzt, um nach Paketverlust schneller auf die Stau-Situation zu reagieren.
- Empfänger informiert den Sender, wenn Pakete außer der Reihe ankommen und somit dazwischen ein Paketverlust vorliegt.
- Der Empfänger bestätigt das letzte korrekte Paket erneut für jedes weitere ankommende Paket außer der Reihe.
- Man spricht dabei von Dup-Acks (duplicate acknowledgments),
- Mehrere aufeinanderfolgende Nachrichten, welche dasselbe Datensegment ACKen.
- Der Sender bemerkt die duplizierten ACKS, und nach dem dritten Duplikat sendet er sofort, vor Ablauf des Timers, das verlorene Paket erneut.
- Da nicht auf den Timerablauf gewartet werden muss, heißt das Prinzip Fast Retransmit.
- Dup-Acks: auch Hinweise darauf, dass ein Paketverlust stattfand, dennoch die folgenden Pakete angekommen sind.
- Das Sendefenster wird nach dem Fehler nur halbiert (kein Slow-Start).
Zusätzlich kann das Sendefenster noch um die Anzahl der Dup-Acks erhöht werden,
- Jedes Dup-Ack steht für ein weiteres Paket, welches den Empfänger erreicht hat.
- Dadurch kann nach dem Fehler schneller wieder die volle Sendeleistung erreicht werden.
- Das Prinzip nennt man Fast-Recovery.
= Dokumentation = == Man-Pages == == Info-Pages == = Links = == Intern == == Weblinks == = Testfragen =
Testfrage 1
Antwort1
Testfrage 2
Antwort2
Testfrage 3
Antwort3
Testfrage 4
Antwort4
Testfrage 5
Antwort5