Netzwerkkommunikation oder: wie Knoten reden

Transport-Layer

Nun haben wir also erfahren, wie die Daten von einem Rechner zum anderen gelangen. Was aber nun, wenn mehrere Programme auf einem PC gleichzeitig mit anderen Rechnern kommunizieren wollen – Beispielsweise, wenn wir mit einem Browser im WWW surfen und gleichzeitig Mails abrufen wollen? Irgendwie müssen die Daten also auch einzelnen Prozessen zugeordnet werden oder – um es mit unserer Post-Analogie zu verdeutlichen: Damit ein Brief, der im Postfach der Firma Hinz und Kunz AG liegt, auch bei Sekretärin Mustermann in Zimmer 4242 ankommt, wird noch so etwas wie eine Hauspost.
Diese „Hauspost“ ist ein Transport-Layer-Protokoll. Verwendet werden hier hauptsächlich TCP und UDP.

Portnummern

Die Zimmernummern heißen bei TCP und UDP Portnummern. Eine Portnummer ist 16 Bit lang, Demnach ist die kleinste Portnummer 0 und die größte 2^16-1=65535.
Die ersten 1024 Ports bilden dabei die so genannten Well Known Ports, d.h. diejenigen, die fest einem bestimmten Dienst zugeordnet sind. Das ist in etwa so, wie, wenn Sekretariat, Kantine, Betriebsrat, Büro vom Chef und Hausmeister bei jeder Firma an der selben Stelle zu finden wären…
Ebenso können Ports im Bereich 1024 bis 49151 registriert werden, sodass auch hier bestimmte Dienste erwartet werden können.
Entsprechende Listen gibt es z.B. in der Wikipedia.

UDP

RFC 768

UDP ist der verbindungslose Dienst in der Transportschicht. Das funktioniert in etwa so, wie die Briefpost: Man schickt einen Brief mit optionalem Absender(Quell-Port) an die auf dem Umschlag(Header) angegebene Adresse(Ziel-Port) und, wenn der Empfänger antworten will, muss der selbst einen Brief schreiben und abschicken. Und, wenn der Absender nicht angegeben ist, kann man gar nicht antworten. Das nennt sich dann verbindungslos. UDP ist ein sehr einfaches Protokoll und wird überall da eingesetzt, wo es schnell gehen muss oder, wo ein großer Overhead nur stören würde. Ein Beispiel ist VoIP also die Internettelefonie. Dabei ist es zu tolerieren, wenn kleinere Übertragungsfehler existieren. Dadurch wird die Stimme vielleicht etwas undeutlicher und es rauscht vielleicht im Hintergrund etwas, aber das Telefonieren ist so immer noch möglich. Wenn es jetzt aber immer ein paar Sekunden dauern würde, bis das gesprochene Wort am anderen Ende ankommt, so ist das wohl eher… suboptimal. Deshalb wird hier ein einfaches Protokoll benötigt, das gewährleistet, dass sich die Verzögerungszeiten in Grenzen halten. Und genau das macht UDP.

TCP

RFC 793

Ganz anders ist das bei TCP. TCP ist der verbindungsorientierte Dienst im Transport-Layer, d.h. es wird zuerst einmal eine Verbindung zwischen den beiden Enden aufgebaut und über diese Verbinung kann der Empfänger dann auch gleich antworten. Das ist in etwa so, wie beim Telefonieren. Da muss man auch nicht neu wählen, nur weil man dem Gesprächspartner antworten will. Eigentlich sind die beiden Kommunikationspartner also gleichberechtigt. Jeder kann Sender und jeder kann Empfänger sein. Im Folgenden wollen wir zwecks besserem Verständnis aber davon ausgehen, dass eine Seite nur sendet und die andere nur empfängt. Das macht die Beispiele einfacher.

TCP bietet aber noch viel mehr: Flusskontrolle(Flow Control), Überlastkontrolle(Congestion Control), Zuverlässiger in-order Datenversand, etc.
Sehen wir uns nun einmal genauer an, was das heißt:

Sendet man ein Paket per UDP, geht das zwar recht schnell, dafür sind verschiedene Dinge nicht gewährleistet: Nacheinander geschickte Pakete können in einer anderen Reihenfolge beim Empfänger ankommen(Theoretisch können diese ja unterschiedliche Wege durch das Internet nehmen, Und, wenn das erste eben nochmal kurz in Australien vorbeischauen will, was zwar nicht wahrscheinlich, aber bei einseitiger Netzlast möglich ist, dann braucht es eben länger, als das zweite, das den direkten Weg nimmt), Bei TCP kann das nicht passieren. eine falsche Reihenfolge wird erkannt und ggf. auf das fehlende Paket gewartet, bis das schon empfangene der Empfängeranwendung übergeben wird. Geht ein Paket einmal verloren, was vorkommen kann, wenn ein Router überlastet ist und nicht genügend Kapazität hat um es zwischenzuspeichern, wird es eben – ohne, dass der Benutzer etwas davon bemerkt – noch einmal angefordert und ein zweites Mal übertragen. Ebenso passiert das bei beschädigten Paketen. TCP bietet also einen zuverlässigen in-order Datenversand.

TCP macht aber noch mehr: Ist z.B. der Sender schneller als der Empfänger(z.B., wenn jemand mit Modem im Internet surft und einen großen Download tätigt), dann wird immer genau so schnell bzw. so viel gesendet, wie der Empfänger verkraften kann(Flusskontrolle).
Ebenso wird versucht das Netz nicht zu überlasten, und so einem „Stau“ vorzubeugen(Überlastkontrolle).

Wie aber schafft das TCP? Zuerst einmal erhält jedes Paket eine Sequenznummer. Daran können Duplikate, sowie fehlende Pakete ermittelt werden. Jedes Mal, wenn der Empfänger ein Paket erhalten hat, sendet er eine Nachricht an dem Sender mit der Meldung „Akzeptiert“(im TCP-Header wird dazu ein spezielles ACK-Flag[5] gesetzt) und der Sequenznummer, die er als nächstes erwartet(d.h. es werden genau genommen nicht die Pakete einzeln bestätigt, sondern nur gesagt „bis dahin hab ich alle“. Das nennt sich dann kumulatives ACK). Dabei gelten die Sequenznummern nicht Segment- sondern byteweise, d.h. für jedes gesendete Nutzdaten-Byte wird die Sequenznummer um eins erhöht. Beispiel:

1
2
3
4
5
Sender                       Empfänger
[seq=500, 512B Daten]  ---->
             <---- [seq=300, ACK=1013]
[seq=1013, 128B Daten] ---->
             <---- [seq=300, ACK=1141]

Da die ACK-Segmente, die der Empfänger sendet, keine Daten enthalten, werden auf der Empfänger-Seite die Sequenznummern nicht erhöht. Durch die Sequenznummern lassen sich verloren gegangene Pakete erkennen. Auch lässt sich daraus die richtige Reihenfolge der Pakete ermitteln. Und dadurch, dass empfangene Pakete mit einer ACK-Nachricht bestätigt werden, weiß auch die Sender-Seite, ob und welche Pakete noch fehlen und kann diese ggf. nochmals senden. Ob dabei nur das fehlende Paket oder alle ab dem fehlenden neu übertragen werden, hängt von der konkreten Implementierung ab(siehe hierzu: Go-Back-N vs. Selective Repeat).

Die initiale(=anfängliche) Sequenznummer für die eine wie die andere Seite werden beim Verbindungsaufbau ausgetauscht: Zuerst sendet der Client ein Paket mit seiner initialen Sequenznummer(die vorher mehr oder weniger zufällig bestimmt wird) und dem SYN-Flag an den Server. Der Antwortet mit seiner initialen Sequenznummer und den Flags SYN und ACK. Der Client bestätigt nun mit ACK und kann dabei schon die ersten Daten senden. Die Verbindung ist aufgebaut. Dieses Verfahren nennt sich Drei-Wege-Handshake.

1
2
3
4
Client                               Server
[seq=500, SYN]  ---->
              <---- [seq=300, SYN, ACK=501]
[seq=500, ACK=301 + ggf. Daten] ---->

ganz ähnlich ist es beim Verbindungsabbau:

1
2
3
4
5
Client                    Server
[seq=3142, FIN]     ---->
        <---- [seq=412, ACK=3143]
        <----      [seq=412, FIN]
[seq=3142, ACK=413] ---->

Pipelining

Durch die Wartezeiten auf die ACK-Segmente wird eigentlich Zeit und damit Performance verschwendet. Auch hier bietet TCP eine Lösung: Es werden einfach schon weitere Pakete gesendet bevor das vorherige akzeptiert wurde. Dadurch, dass ja kumulative ACKs verwendet werden, werden dann auch weniger ACKs benötigt und dadurch weiter Bandbreite gespart.

Socket

Um TCP bzw. UDP zu benutzen, muss man nicht die einzelnen Segmente selbst zusammenbauen. Das erledigt eine dafür vorgesehene API[6]. Unter Windows heißt diese Winsock und orientiert sich an den „Ur-Sockets“ der Berkeley Software Distribution (BSD). Letztere werden auch heute noch u.a. in Linux verwendet.
Unter einem Socket kann man sich so etwas, wie einen Datenkanal vorstellen. Man steckt ein Paket hinein und am anderen Ende kommt es wieder heraus. Alles, was zwischendrin passiert(alles auf Physical, Link-, Network- und Transport-Layer) muss den Benutzter des Sockets nicht oder kaum interessieren. Es passiert ganz automatisch, Windows bzw. die Winsock.dll(bzw. die Sockets-Implementierung anderer Systeme) kümmert sich darum.
Damit nun der Socket überhaupt weiß, wohin er die Daten schicken soll, benötigt er aber ein paar Informationen: Ziel-IP(an welchen Rechner soll das alles geschickt werden?), Ziel-Port(wo steckt das Programm, das die Daten empfangen soll?) und bei TCP(TCP ist ja bidirektional; man spricht hier von Voll-Duplex): Quell-IP und Quell-Port, also den Absender der Daten.
Man sagt in diesem Zusammenhang auch „Ein UDP-Socket besteht aus Ziel-IP und Ziel-Port.“ und „Ein TCP-Socket besteht aus Ziel-IP, Ziel-Port, Quell-IP und Quell-Port“.

Des weiteren wird auch oft davon gesprochen einen Port „zu öffnen“. Effektiv bedeutet dies aber nur über einen TCP- oder UDP-Socket auf diesem Port zu lauschen. Alle andern Ports sind automatisch „geschlossen“. Desktop-Firewalls „schließen“ also keine Ports, wie die Hersteller solcher Programme gerne behaupten, sondern versuchen nur zu kontrollieren, wer einen Port „öffnen“ darf.

[5] „ACK“ steht hier für Acknowledgement
[6] Application Programming Interface

Kapitel: | Zurück | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Weiter |

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert