|
|
Zeile 176: |
Zeile 176: |
| = Konfiguration = | | = Konfiguration = |
| == Dateien == | | == Dateien == |
|
| |
| = Anwendungen =
| |
| == 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 '''I'''nternet '''A'''ssigned '''N'''umbers '''A'''uthority (IANA)
| |
| ** z.B. ist Port 80 für '''H'''yper'''t'''ext '''T'''ransfer '''P'''rotocol (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.
| |
|
| |
| == Verbindungsverwaltung ==
| |
| === 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 ===
| |
| [[Datei:Tcp-handshake.svg|mini|500px| TCP-Handshake]]
| |
|
| |
| # 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 ====
| |
|
| |
| {| class="wikitable"
| |
| |-
| |
| |width="60px"| 1. || SYN-SENT ||width="60px"| → || <SEQ=100><CTL=SYN> ||width="60px"| → || 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 ===
| |
| [[Datei:TCP-Teardown.svg|mini|500px| TCP-Teardown]]
| |
|
| |
| * 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 ==
| |
| [[Datei:Tcp daten.svg|mini| 450px | Segmentierung der Nutzdaten]]
| |
|
| |
| === 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 ===
| |
| [[Datei:Tcp transfer.png|mini|450px| Beispiel eines Datentransfers]]
| |
| # 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 ===
| |
| [[Datei:Sliding window.svg|mini| Sliding Window]]
| |
|
| |
| 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 ====
| |
| [[Datei:TCPSlowStartundCongestionAvoidance.svg|mini|450px|Grafische Darstellung des Slow-Start-Algorithmus]]
| |
|
| |
| * 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''.
| |
|
| |
| [[Datei:Tcp verbindung.png|none|750px|Verwaltung der TCP-Verbindungen als endlicher Automat]]
| |
|
| |
|
| = Dokumentation = | | = Dokumentation = |