
|
|
TCP - Datenübertragung
Um das Konzept des Verbindungsaufbaus und der nun folgenden Datenübertragung
besser zu verstehen, kann man sich beide Endpunkte einer TCP-Verbindung
folgendermaßen veranschaulichen:
Sowohl der Client- als auch der Serverprozess unterhalten Puffer für Senden und
Empfangen. In die Sendepuffer werden jeweils Daten geschrieben, die zur Gegenseite
übertragen werden sollen. Normalerweise wird damit gewartet, bis eine gewisse
Mindestmenge an Daten ("Chunkgröße") im Puffer ist, bevor die Übertragung beginnt.
Bei interaktiven Anwendungen wie z.B. Telnet wäre dies nicht zweckmäßig, dort wird
immer sofort gesendet. Die übertragenen Daten landen auf der Gegenseite zunächst
im Empfangspuffer und können dort durch einen Prozess der nächsthöheren
Protokollschicht ausgelesen werden.
Mit dem Verbindungsaufbau bestimmt zunächst der Clientprozess senderseitig eine
Sequenznummer und überträgt sie zum Server-Prozess, der sie empfangsseitig
einträgt. Der gleiche Vorgang läuft nun bei der Bestätigung des Verbindungsaufbaus
nochmal in der Gegenrichtung statt.
So läuft von nun an der gesamte Datentransfer: Sobald eine Seite etwas sendet,
wird ein TCP-Paket mit der aktuellen Sende-Sequenznummer erzeugt und diese
anschließend um die Anzahl der übertragenen Nutzbytes erhöht. Der Empfänger
stellt die Nutzdaten in den Empfangspuffer und erhöht seine Empfangs-Sequenznummer
um die Anzahl der empfangenen Bytes. Der Empfänger sendet nun eine Bestätigung,
d.h. ein Datenpaket mit dem Flag "ACK". Dieses kann wahlweise leer sein oder
Daten enthalten, die ohnehin zur Übertragung anstehen. Auf jeden Fall enthält
das Paket als Bestätigungsnummer die neue Sequenznummer. Sobald das Paket
ankommt, weiss der Sender, dass seine Daten gut angekommen sind und kann dies
in einer Variablen (im Beispiel "bestätigt" genannt) ablegen.
Nun kommt noch eine weitere Größe ins Spiel: Es kann passieren, dass die Daten
auf einer Seite nicht so schnell aus dem Empfangspuffer gelesen werden, wie neue
nachgeliefert werden. Um einen Pufferüberlauf auszuschließen, wird dessen
Restkapazität mit jedem TCP-Paket im Feld "Fenstergröße" übermittelt. Die
Gegenstelle kann sich folglich darauf einstellen und seine Übertragungen
vorübergehend einstellen, wenn der Puffer überzulaufen droht.
TCP benötigt Mechanismen für die Absicherung der übertragenen Daten gegen
Verlust. Daher wird für jedes gesendete Paket ein Timer gestartet. Läuft
dieser ab, bevor das Paket bestätigt wurde, wird es nochmals übertragen. Es
wird übrigens nicht bei jedem Paket auf die Bestätigung gewartet - solange
es die Fenstergröße des Empfängers zulässt, werden Pakete gesendet.
Geht bei der Übertragung etwas schief, wird der Empfänger wahrscheinlich
anstelle des erwarteten Pakets bereits das nächste erhalten, welches er
an der höheren Sequenznummer erkennt. Er sendet dann ein Paket, in dem er
das ACK-Flag setzt, als Bestätigungsnummer aber die Sequenznummer einträgt,
die er eigentlich erwartet hätte. Der Sender erhält nun für eine bereits
bestätigte Sequenznummer eine zweite Bestätigung. Er schießt daraus, dass
wohl das nachfolgende Paket verlorengegangen ist und sendet dieses nochmal.
Es bleibt der TCP-Implementierung des Empfängers überlassen, ob er die
zwischenzeitlich enpfangenen Pakete mit höheren Sequenznummern aufbewahrt und
nach Eintreffen des Nachzüglers mit der Sequenznummer des nun erwarteten
nächsten Pakets bestätigt oder ob er alle Folgepakete verwirft und diese nun
nacheinander nochmal anfordert. Ersteres ist natürlich wesentlich performanter,
die zweite Lösung hingegen wesentlich leichter zu implementieren.
|
|