Netzwerkprogrammierung - TCP. Client-Server-Anwendung auf einem TCP-Stream-Socket. Festlegen von IP-Parameterwerten

TCP lässt sich auf natürliche Weise in eine Client/Server-Umgebung integrieren (siehe Abbildung 10.1). Serveranwendung Käfer Eingehende Verbindungsanfragen (abhören). Beispielsweise warten WWW-, Dateiübertragungs- oder Terminalzugriffsdienste auf Anfragen von Clients. Die Kommunikation in TCP wird durch entsprechende Routinen initiiert, die eine Verbindung zum Server initiieren (siehe Kapitel 21 zur Socket-Programmierschnittstelle).

Reis. 10.1. Der Client ruft den Server an.

In Wirklichkeit kann der Client ein anderer Server sein. Beispielsweise können Mailserver eine Verbindung zu anderen herstellen Mailserver um Nachrichten weiterzuleiten Email zwischen Computern.

10.2 TCP-Konzepte

In welcher Form sollten Anwendungen Daten in TCP senden? In welcher Form überträgt TCP Daten an IP? Wie identifizieren die sendenden und empfangenden TCP-Protokolle die Verbindung zwischen Anwendungen und den für ihre Implementierung erforderlichen Datenelementen? Alle diese Fragen werden in den folgenden Abschnitten beantwortet, in denen die Grundkonzepte von TCP beschrieben werden.

10.2.1 Eingabe- und Ausgabedatenströme

Konzeptionell Beim Verbindungsmodell leitet eine Anwendung einen Datenstrom an eine Peer-Anwendung weiter. Gleichzeitig ist es in der Lage, einen Datenstrom von seinem Verbindungspartner zu empfangen. TCP bietet Vollduplex(Vollduplex) Betriebsmodus, in dem gleichzeitig bedient wird zwei Ströme Daten (siehe Abb. 10.2).


Reis. 10.2. Anwendungen tauschen Datenströme aus.

10.2.2 Segmente

TCP kann den Datenstrom, der eine Anwendung verlässt, in eine Form umwandeln, die für die Speicherung in Datagrammen geeignet ist. Auf welche Weise?

Die Anwendung sendet Daten an TCP und dieses Protokoll platziert sie dort Ausgabepuffer(Sendepuffer). Als nächstes schneidet TCP Datenstücke aus dem Puffer aus und sendet sie, wobei ein Header hinzugefügt wird (dies generiert Segmente- Segment). In Abb. 10.3 zeigt, wie die Daten aus Ausgabepuffer TCP ist in Segmente paketiert. TCP übergibt das Segment zur Zustellung als separates Datagramm an IP. Durch das Packen von Daten in Blöcke mit der richtigen Länge wird eine effiziente Weiterleitung gewährleistet. Daher wartet TCP, bis die entsprechende Datenmenge im Ausgabepuffer verfügbar ist, bevor es ein Segment erstellt.


Reis. 10.3 Erstellen eines TCP-Segments

10.2.3 Schieben

Große Datenmengen lassen sich jedoch oft nicht auf reale Anwendungen übertragen. Wenn beispielsweise ein Endbenutzer-Clientprogramm eine interaktive Sitzung mit initiiert Remote-Server, dann gibt der Benutzer nur noch Befehle ein (anschließend drückt er die Taste). Zurückkehren).

Das Client-Programm des Benutzers benötigt TCP, um zu wissen, dass Daten an den Remote-Host gesendet werden, und um diesen Vorgang sofort auszuführen. In diesem Fall wird es verwendet Herausdrücken(drücken).

Wenn Sie sich die Vorgänge in einer interaktiven Sitzung ansehen, werden Sie viele Segmente mit wenigen Daten finden, und außerdem sind in fast jedem Datensegment Popper zu finden. Allerdings sollte Pushing während der Dateiübertragung nicht verwendet werden (mit Ausnahme des allerletzten Segments), da TCP die Daten dann am effizientesten in Segmente packen kann.

10.2.4 Dringende Daten

Das Datenweiterleitungsmodell der Anwendung umfasst einen geordneten Bytestrom, der zum Ziel transportiert wird. Nehmen wir noch einmal Bezug auf das Beispiel einer interaktiven Sitzung: Angenommen, der Benutzer hat eine Taste gedrückt Aufmerksamkeit(Achtung) oder brechen(unterbrechen). Die Remote-Anwendung muss in der Lage sein, die störenden Bytes zu überspringen und so schnell wie möglich auf den Tastendruck zu reagieren.

Mechanismus dringende Daten(dringende Daten) markiert spezielle Informationen in einem Segment als dringend. Dadurch teilt TCP seinem Peer mit, dass das Segment dringende Daten enthält und kann angeben, wo es sich befindet. Der Partner muss diese Informationen schnellstmöglich an die Zielanwendung weiterleiten.

10.2.5 Anwendungsports

Der Client muss den Dienst identifizieren, auf den er zugreifen möchte. Dies erfolgt durch die Angabe der IP-Adresse des Host-Dienstes und seiner TCP-Portnummer. Wie bei UDP reichen die TCP-Portnummern von 0 bis 65535. Ports im Bereich von 0 bis 1023 werden als bekannt bezeichnet und für den Zugriff auf Standarddienste verwendet.

Mehrere Beispiele bekannter Ports und ihre entsprechenden Anwendungen sind in Tabelle 10.1 aufgeführt. Dienstleistungen Verwerfen(Port 9) und berechnet(Port 19) sind TCP-Versionen von Diensten, die uns bereits über UDP bekannt sind. Es ist zu beachten, dass der Datenverkehr zu Port 9 des TCP-Protokolls vollständig vom Datenverkehr zu Port 9 des UDP-Protokolls isoliert ist.


Tabelle 10.1 Bekannte TCP-Ports und ihre entsprechenden Anwendungen

Hafen Anwendung Beschreibung
9 Verwerfen Alle eingehenden Daten abbrechen
19 Aufladen Zeichengenerator. Charakter-Stream-Austausch
20 FTP-Daten FTP-Datenweiterleitungsport
21 FTP Port für FTP-Dialog
23 TELNET Port für die Fernregistrierung über Telnet
25 SMTP SMTP-Protokollport
110 POP3 Mail-Sampling-Service für Personalcomputer
119 NNTP Zugriff auf Online-Nachrichten

Was ist mit den von Clients verwendeten Ports? In seltenen Fällen funktioniert der Client nicht über einen bekannten Port. Wenn man jedoch in solchen Situationen eine Verbindung öffnen möchte, wird das Betriebssystem oft aufgefordert, ihm einen ungenutzten und nicht reservierten Port zuzuweisen. Am Ende der Verbindung muss der Client diesen Port zurückgeben, danach kann der Port von einem anderen Client wiederverwendet werden. Da der nicht reservierte Nummernpool mehr als 63.000 TCP-Ports enthält, können Client-Portbeschränkungen ignoriert werden.

10.2.6 Socket-Adressen

Wie wir bereits wissen, nennt man die Kombination aus IP-Adresse und Port für die Kommunikation Adress-Socket. Eine TCP-Verbindung wird vollständig durch die Socket-Adresse an jedem Ende identifiziert dieser Verbindung. In Abb. Abbildung 10.4 zeigt die Verbindung zwischen einem Client mit Socket-Adresse (128.36.1.24, Port = 3358) und einem Server mit Socket-Adresse (130.42.88.22, Port = 21).

Reis. 10.4. Socket-Adressen

Der Header jedes Datagramms enthält die Quell- und Ziel-IP-Adressen. Später werden Sie sehen, dass die Quell- und Zielportnummern im TCP-Segmentheader angegeben sind.

Normalerweise ist ein Server in der Lage, mehrere Clients gleichzeitig zu verwalten. Allen seinen Clients werden gleichzeitig eindeutige Server-Socket-Adressen zugewiesen (siehe Abb. 10.5).


Reis. 10.5. Mehrere Clients sind mit Server-Socket-Adressen verbunden

Da ein Datagramm ein TCP-Verbindungssegment enthält, das durch IP-Adressen und Ports identifiziert wird, ist es für einen Server sehr einfach, mehrere Verbindungen zu Clients zu verfolgen.

10.3 TCP-Zuverlässigkeitsmechanismus

In diesem Abschnitt betrachten wir den TCP-Mechanismus, der zur zuverlässigen Übermittlung von Daten unter Beibehaltung der Übertragungsreihenfolge und zur Vermeidung von Verlusten oder Duplikaten verwendet wird.

10.3.1 Nummerierung und Bestätigung

TCP verwendet Nummerierung und Bestätigung (ACK), um eine zuverlässige Datenübertragung sicherzustellen. Das TCP-Nummerierungsschema ist etwas ungewöhnlich: jedenüber die Verbindung weitergeleitet Oktett gilt als mit einer Seriennummer versehen. Der TCP-Segmentheader enthält eine Sequenznummer das erste Oktett der Daten in diesem Segment.

Der Empfänger muss bestätigen, dass die Daten empfangen wurden. Wenn die Bestätigung nicht innerhalb des Timeout-Intervalls eintrifft, werden die Daten erneut übertragen. Diese Methode heißt positive Bestätigung mit Relais(positive Bestätigung mit erneuter Übertragung).

Der Empfänger von TCP-Daten prüft streng die eingehenden Sequenznummern, um sicherzustellen, dass die Daten der Reihe nach empfangen werden und keine Teile fehlen. Da die ACK zufällig verloren gehen oder verzögert werden kann, können beim Empfänger doppelte Segmente eintreffen. Mithilfe von Sequenznummern können Sie doppelte Daten identifizieren und diese dann verwerfen.

In Abb. Abbildung 10.6 zeigt eine vereinfachte Ansicht von Timeout und Neuübertragung in TCP.


Reis. 10.6. Timeout und erneute Übertragung in TCP

10.3.2 Port-, Sequenz- und ACK-Felder im TCP-Header

Wie in Abb. 10.7 bieten die ersten paar Felder des TCP-Headers Platz für die Quell- und Zielportwerte, die Sequenznummer des ersten Bytes der eingeschlossenen Daten und ein ACK, das der Sequenznummer entspricht nächste Byte, das am anderen Ende erwartet wird. Mit anderen Worten: Wenn TCP alle Bytes bis zu 30 von seinem Peer empfängt, hat dieses Feld den Wert 31 und gibt damit das Segment an, das als nächstes weitergeleitet werden soll.


Reis. 10.7. Anfangswerte in TCP-Header-Feldern

Ein kleines Detail kann nicht übersehen werden. Nehmen wir an, dass TCP die Bytes 1 bis 50 gesendet hat und es keine weiteren Daten zum Senden gibt. Wenn Daten von einem Peer empfangen werden, muss TCP den Empfang bestätigen, indem es einen Header ohne die daran angehängten Daten sendet. Selbstverständlich enthält dieser Header den Wert ACK. Im Sequenzfeld ist der Wert 51, d.h. die Nummer des nächsten Bytes, das beabsichtigt TCP senden. Wenn TCP die nächsten Daten sendet, enthält der neue TCP-Header auch das Sequenzfeld 51.

10.4 Verbindung herstellen

Wie verbinden sich zwei Anwendungen miteinander? Vor der Kommunikation ruft jeder von ihnen eine Unterroutine auf, um einen Speicherblock zu bilden, der zum Speichern der TCP- und IP-Parameter einer bestimmten Verbindung verwendet wird, zum Beispiel Socket-Adressen, aktuelle Sequenznummer, anfänglicher Lebensdauerwert usw.

Die Serveranwendung wartet auf das Erscheinen eines Clients, der, um Zugriff auf den Server zu erhalten, eine Anfrage stellt Verbindung(verbinden) und identifiziert die IP-Adresse und den Port des Servers.

Da ist einer technisches Merkmal. Jede Seite beginnt, jedes Byte nicht mit eins, sondern mit zu nummerieren zufällige Seriennummer(Warum das so ist, erfahren wir später). Die ursprüngliche Spezifikation empfiehlt, die anfängliche Sequenznummer auf der Grundlage eines externen 32-Bit-Timers zu generieren, der etwa alle 4 µs erhöht wird.

10.4.1 Verbindungsszenario

Der Verbindungsvorgang wird oft als Drei-Wege-Handshake bezeichnet, da zum Aufbau einer Verbindung drei Nachrichten ausgetauscht werden: SYN, SYN und ACK.

Beim Verbindungsaufbau tauschen die Partner drei wichtige Informationen aus:

1. Pufferspeicher zum Empfangen von Daten

2. Maximale Datenmenge, die in einem eingehenden Segment übertragen wird

3. Startsequenznummer für ausgehende Daten

Beachten Sie, dass jede Partei die Operationen 1 und 2 zur Angabe verwendet die Grenzen, innerhalb derer die andere Partei handeln wird. Ein Personalcomputer verfügt möglicherweise über einen kleinen Empfangspuffer, ein Supercomputer jedoch möglicherweise über einen riesigen Puffer. Speicherstruktur persönlicher Computer kann eingehende Datenblöcke auf 1 KB begrenzen, und der Supercomputer verwaltet große Segmente.

Die Möglichkeit zu steuern, wie die andere Partei Daten sendet, ist wichtige Eigenschaft und bietet TCP/IP-Skalierbarkeit.

In Abb. Abbildung 10.8 zeigt ein Beispiel für ein Verbindungsskript. Um die Zeichnung nicht zu überladen, werden sehr einfache Anfangssequenznummern dargestellt. Beachten Sie, dass in dieser Abbildung der Client größere Segmente empfangen kann als der Server.


Reis. 10.8. Eine Verbindung herstellen

Folgende Vorgänge werden ausgeführt:

1. Der Server wird initialisiert und ist bereit, eine Verbindung zu Clients herzustellen (dieser Zustand wird als passiv offen bezeichnet).

2. Der Client fordert TCP auf, eine Verbindung zum Server an der angegebenen IP-Adresse und dem angegebenen Port zu öffnen (dieser Zustand wird als aktiv offen bezeichnet).

3. Der Client-TCP erhält eine anfängliche Sequenznummer (in in diesem Beispiel- 1000) und sendet Synchronisierungssegment(Segment synchronisieren - SYN). Dieses Segment trägt die Sequenznummer, die Größe des Empfangsfensters (4 KB) und die Größe des größten Segments, das der Client empfangen kann (1460 Byte).

4. Wenn ein SYN eintrifft, empfängt der Server TCP meins Startsequenznummer (3000). Er sendet ein SYN-Segment, das die Startsequenznummer (3000), ACK 1001 (was bedeutet, dass das erste vom Client gesendete Byte die Nummer 1001 hat), die Größe des Empfangsfensters (4 KB) und die Größe des größten Segments, das der Server verarbeiten kann, enthält empfangen (1024 Bytes).

5. Client TCP sendet, nachdem er eine SYN/ACK-Nachricht vom Server erhalten hat, ACK 3001 zurück (das erste Byte der vom Server gesendeten Daten sollte die Nummer 3001 haben).

6. Der Client-TCP weist seine Anwendung an, die Verbindung zu öffnen.

7. Der Server-TCP informiert seine Anwendung über das Öffnen der Verbindung, nachdem er eine ACK-Nachricht vom Client-TCP erhalten hat.

Client und Server geben ihre Regeln für die empfangenen Daten bekannt, synchronisieren ihre Sequenznummern und sind bereit für den Datenaustausch. Die TCP-Spezifikation ermöglicht auch ein anderes (nicht sehr erfolgreiches) Szenario, bei dem sich Peer-Anwendungen gleichzeitig aktiv gegenseitig öffnen.

10.4.2 IP-Parameterwerte einstellen

Eine Anwendungsanforderung zum Herstellen einer Verbindung kann auch Parameter für die IP-Datagramme angeben, die die Verbindungsdaten übertragen. Wenn kein bestimmter Parameterwert angegeben ist, wird der Standardwert verwendet.

Beispielsweise kann eine Anwendung einen gewünschten Wert für die IP-Priorität oder den Diensttyp auswählen. Da jede der angeschlossenen Parteien unabhängig ihre eigene Priorität und Art des Dienstes festlegt, können diese Werte theoretisch für verschiedene Richtungen des Datenflusses unterschiedlich sein. In der Praxis werden in der Regel für jede Austauschrichtung die gleichen Werte verwendet.

Wenn eine Anwendung staatliche oder militärische Sicherheitsoptionen umfasst, muss jeder Endpunkt der Verbindung dieselben Sicherheitsstufen verwenden, sonst wird die Verbindung nicht hergestellt.

10.5 Datenübertragung

Die Datenübertragung beginnt nach Abschluss der dreistufigen Bestätigung des Verbindungsaufbaus (siehe Abbildung 10.9). Der TCP-Standard ermöglicht die Aufnahme normaler Daten in Bestätigungssegmente, diese werden jedoch erst nach Abschluss der Verbindung an die Anwendung übermittelt. Um die Nummerierung zu vereinfachen, werden 1000-Byte-Nachrichten verwendet. Jedes TCP-Header-Segment verfügt über ein ACK-Feld, das die Byte-Sequenznummer identifiziert, die voraussichtlich vom Verbindungspartner empfangen wird.


Reis. 10.9. Einfacher Datenaustausch und ACK-Fluss

Das erste vom Client gesendete Segment enthält die Bytes 1001 bis 2000. Sein ACK-Feld sollte den Wert 3001 enthalten, der die Byte-Sequenznummer angibt, die voraussichtlich vom Server empfangen wird.

Der Server antwortet dem Client mit einem Segment, das 1000 Byte Daten enthält (beginnend mit der Nummer 3001). Sein TCP-Header-ACK-Feld zeigt an, dass die Bytes 1001 bis 2000 bereits erfolgreich empfangen wurden, sodass die nächste vom Client erwartete Segmentsequenznummer 2001 sein sollte.

Der Client sendet dann Segmente beginnend mit den Bytes 2001, 3001 und 4001 in der angegebenen Reihenfolge. Beachten Sie, dass der Client nicht nach jedem gesendeten Segment auf eine Bestätigung wartet. Die Daten werden so lange an den Peer gesendet, bis dessen Pufferplatz voll ist (wir werden weiter unten sehen, dass der Empfänger die Menge der an ihn gesendeten Daten sehr genau angeben kann).

Der Server spart Verbindungsbandbreite, indem er eine einzige ACK verwendet, um die erfolgreiche Weiterleitung aller Segmente anzuzeigen.

In Abb. Abbildung 10.10 zeigt die Datenübertragung, wenn das erste Segment verloren geht. Nach Ablauf des Timeouts wird das Segment erneut übertragen. Beachten Sie, dass der Empfänger beim Empfang eines verlorenen Segments eine einzelne ACK sendet, die die Weiterleitung beider Segmente bestätigt.


Reis. 10.10. Datenverlust und Neuübertragung

10.6 Eine Verbindung schließen

Der normale Verbindungsabbau erfolgt nach dem gleichen Triple-Handshake-Verfahren wie beim Verbindungsaufbau. Jeder Teilnehmer kann mit dem Schließen der Verbindung beginnen, indem er das folgende Szenario verwendet:

A:

B:"Bußgeld".

IN:„Ich habe den Job auch erledigt.“

A:"Bußgeld".

Nehmen wir das folgende Szenario an (obwohl es äußerst selten verwendet wird):

A:„Ich bin fertig. Es sind keine Daten mehr zum Senden vorhanden.“

IN:„Okay. Es gibt jedoch einige Daten…“

IN:„Ich habe den Job auch erledigt.“

A:"Bußgeld".

Im folgenden Beispiel wird die Verbindung vom Server geschlossen, wie es bei Client/Server-Verbindungen häufig der Fall ist. In diesem Fall, nachdem der Benutzer der Sitzung beigetreten ist Telnet Der Logout-Befehl veranlasst den Server, eine Anfrage zum Schließen der Verbindung zu initiieren. In der in Abb. 10.11 werden folgende Aktionen ausgeführt:

1. Die Anwendung auf dem Server weist TCP an, die Verbindung zu schließen.

2. Der TCP-Server sendet ein letztes Segment (Final Segment – ​​FIN) und informiert seinen Peer darüber, dass keine weiteren Daten zu senden sind.

3. Der TCP des Clients sendet eine ACK im FIN-Segment.

4. Das TCP des Clients teilt seiner Anwendung mit, dass der Server die Verbindung schließen möchte.

5. Die Clientanwendung weist ihr TCP an, die Verbindung zu schließen.

6. Der TCP-Client sendet eine FIN-Nachricht.

7. Der TCP-Server empfängt die FIN vom Client und antwortet mit einer ACK-Nachricht.

8. Das TCP des Servers weist seine Anwendung an, die Verbindung zu schließen.


Reis. 10.11. Schließen einer Verbindung

Beide Parteien können gleichzeitig mit dem Abschluss beginnen. In diesem Fall wird der normale Verbindungsabschluss abgeschlossen, nachdem jeder Peer eine ACK-Nachricht gesendet hat.

10.6.1 Abrupte Beendigung

Jede Partei kann eine abrupte Beendigung (abrupte Schließung) der Verbindung verlangen. Dies ist akzeptabel, wenn eine Anwendung eine Verbindung beenden möchte oder wenn TCP ein schwerwiegendes Kommunikationsproblem erkennt, das es nicht selbst lösen kann. Eine abrupte Beendigung wird durch das Senden einer oder mehrerer Reset-Nachrichten an den Peer angefordert, was durch ein bestimmtes Flag im TCP-Header angezeigt wird.

10.7 Flusskontrolle

Der TCP-Empfänger wird mit dem eingehenden Datenstrom geladen und bestimmt, wie viele Informationen er akzeptieren kann. Diese Einschränkung betrifft den TCP-Absender. Die folgende Erklärung dieses Mechanismus ist konzeptionell und Entwickler können ihn auf unterschiedliche Weise in ihren Produkten implementieren.

Während des Verbindungsaufbaus weist jeder Peer Platz für den Eingabepuffer der Verbindung zu und benachrichtigt die andere Partei darüber. Typischerweise wird die Puffergröße als Ganzzahl der maximalen Segmentgrößen ausgedrückt.

Der Datenstrom gelangt in den Eingabepuffer und wird dort gespeichert, bevor er an die Anwendung (definiert durch den TCP-Port) weitergeleitet wird. In Abb. Abbildung 10.12 zeigt einen Eingabepuffer, der 4 KB aufnehmen kann.


Reis. 10.12. Eingangspuffer-Empfangsfenster

Der Pufferraum wird gefüllt, sobald Daten eintreffen. Wenn die empfangende Anwendung Daten aus dem Puffer abruft, wird der frei gewordene Speicherplatz für neue eingehende Daten verfügbar.

10.7.1 Empfangsfenster

Empfangsfenster(Empfangsfenster) – beliebiger Platz im Eingabepuffer, der nicht bereits durch Daten belegt ist. Die Daten verbleiben im Eingabepuffer, bis sie von der Zielanwendung verwendet werden. Warum erfasst die Anwendung nicht sofort Daten?

Ein einfaches Szenario hilft bei der Beantwortung dieser Frage. Nehmen wir an, dass der Client die Datei gesendet hat FTP-Server läuft auf einem sehr ausgelasteten Mehrbenutzer-Computer. Das FTP-Programm muss dann die Daten aus dem Puffer lesen und auf die Festplatte schreiben. Wenn der Server Festplatten-E/A-Vorgänge ausführt, wartet das Programm auf den Abschluss dieser Vorgänge. Zu diesem Zeitpunkt kann ein anderes Programm starten (z. B. nach einem Zeitplan) und zwar währenddessen FTP-Programm beginnt erneut, die nächsten Daten werden bereits im Puffer eintreffen.

Das Empfangsfenster reicht vom letzten bestätigten Byte bis zum Ende des Puffers. In Abb. 10.12 steht zunächst der gesamte Puffer zur Verfügung und somit steht ein 4 KB großes Empfangsfenster zur Verfügung. Wenn das erste KB eintrifft, wird das Empfangsfenster auf 3 KB reduziert (der Einfachheit halber gehen wir davon aus, dass jedes Segment 1 KB groß ist, obwohl dieser Wert in der Praxis je nach den Anforderungen der Anwendung variiert). Durch die Ankunft der nächsten beiden 1-KB-Segmente wird das Empfangsfenster auf 1 KB reduziert.

Jedes vom Empfänger gesendete ACK enthält Informationen über den aktuellen Zustand des Empfangsfensters, abhängig davon, welcher Datenfluss von der Quelle reguliert wird.

In den meisten Fällen wird die Größe des Eingabepuffers beim Verbindungsaufbau festgelegt, obwohl der TCP-Standard nicht vorgibt, wie dieser Puffer verwaltet werden soll. Der Eingabepuffer kann zur Implementierung vergrößert oder verkleinert werden Rückmeldung mit dem Absender.

Was passiert, wenn das ankommende Segment im Empfangsfenster platziert werden kann, aber nicht in der richtigen Reihenfolge ankommt? Es wird allgemein davon ausgegangen, dass alle Implementierungen eingehende Daten in einem Empfangsfenster speichern und nur für den gesamten zusammenhängenden Block mehrerer Segmente eine Bestätigung (ACK) senden. Das ist der richtige Weg, denn andernfalls führt das Verwerfen von Daten, die in der falschen Reihenfolge eintreffen, zu einer erheblichen Leistungseinbuße.

10.7.2 Einreichungsfenster

Das System, das Daten überträgt, muss zwei Merkmale im Auge behalten: wie viele Daten bereits gesendet und bestätigt wurden und wie groß das Empfangsfenster des Empfängers aktuell ist. Aktiv Raum senden(Sendebereich) erstreckt sich vom ersten unbestätigten Oktett bis zum linken Rand des aktuellen Empfangsfensters. Teil Fenster, gebraucht senden, gibt an, wie viele zusätzliche Daten an den Partner gesendet werden können.

Die anfängliche Sequenznummer und die anfängliche Empfangsfenstergröße werden beim Verbindungsaufbau angegeben. Reis. Abbildung 10.13 veranschaulicht einige Merkmale des Datenübertragungsmechanismus.

1. Der Absender beginnt mit einem 4 KB großen Sendefenster.

2. Der Absender sendet 1 KB. Eine Kopie dieser Daten wird aufbewahrt, bis eine Bestätigung (ACK) empfangen wird, da sie möglicherweise erneut übertragen werden muss.

3. Die ACK-Nachricht für das erste KB kommt an und die nächsten 2 KB Daten werden gesendet. Das Ergebnis ist im dritten Teil von oben in Abb. dargestellt. 10.13. 2 KB Speicher bleiben bestehen.

4. Schließlich kommt eine Bestätigung für alle übertragenen Daten (d. h. alle Daten werden vom Empfänger empfangen). ACK stellt die Größe des Sendefensters auf 4 KB wieder her.

Reis. 10.13. Fenster senden

Es gibt mehrere interessante Funktionen, die es wert sind, hervorgehoben zu werden:

■ Der Absender wartet nicht für jedes gesendete Datensegment auf eine Bestätigung. Die einzige Einschränkung bei der Weiterleitung ist die Größe des Empfangsfensters (der Absender darf beispielsweise nur 4K-Einzelbyte-Segmente weiterleiten).

■ Angenommen, der Absender sendet Daten in mehreren sehr kurzen Segmenten (z. B. 80 Byte). In diesem Fall können die Daten für eine effizientere Übertragung neu formatiert werden (z. B. in ein einzelnes Segment).

10.8 TCP-Header

In Abb. Abbildung 10.14 zeigt das Segmentformat (TCP-Header und Daten). Der Header beginnt mit den Quell- und Ziel-Port-IDs. Nächstes nächstes Feld Seriennummer(Sequenznummer) gibt die Position im ausgehenden Datenstrom an, die dieses Segment einnimmt. Feld ACK(Bestätigung) enthält Informationen über das erwartete nächste Segment, das im Eingabedatenstrom erscheinen soll.


Reis. 10.14. TCP-Segment

Es gibt sechs Flaggen:

Feld Datenoffsets(Datenoffset) enthält die Größe des TCP-Headers in 32-Bit-Wörtern. Der TCP-Header muss an einer 32-Bit-Grenze enden.

10.8.1 Option „Maximale Segmentgröße“.

Parameter „maximale Segmentgröße“(maximale Segmentgröße – MSS) wird verwendet, um das größte Datenelement anzugeben, das vom System akzeptiert und verarbeitet werden kann. Allerdings ist der Name etwas ungenau. Normalerweise in TCP Segment als Header plus Daten behandelt. Jedoch maximale Segmentgröße definiert als:

Die Größe des größten empfangbaren Datagramms beträgt 40

Mit anderen Worten: MSS spiegelt das Größte wider Nutzlast beim Empfänger, wenn die TCP- und IP-Header 20 Byte lang sind. Wenn es gibt Zusätzliche Optionen, ihre Länge sollte von der Gesamtgröße abgezogen werden. Daher ist die Datenmenge, die in einem Segment gesendet werden kann, wie folgt definiert:

Angegebener Wert MSS + 40 – (Summe der TCP- und IP-Header-Längen)

Peers tauschen beim Öffnen einer Verbindung normalerweise MSS-Werte in ersten SYN-Nachrichten aus. Wenn das System keinen maximalen Wert für die Segmentgröße angibt, wird der Standardwert von 536 Byte verwendet.

Die maximale Segmentgröße wird als 2-Byte-Einleitung gefolgt von einem 2-Byte-Wert codiert, d. h. Der größte Wert beträgt 2 16 -1 (65.535 Bytes).

MSS schränkt die in TCP gesendeten Daten stark ein: Der Empfänger kann große Werte nicht verarbeiten. Der Absender verwendet jedoch Segmente kleinere Größe, da für die Verbindung auch die MTU-Größe entlang der Route ermittelt wird.

10.8.2 Verwendung von Header-Feldern in einer Verbindungsanfrage

Das erste zum Öffnen einer Verbindung gesendete Segment hat ein SYN-Flag von 1 und ein ACK-Flag von 0. Das anfängliche SYN ist der Einzige ein Segment, das ein ACK-Feld mit dem Wert 0 hat. Beachten Sie, dass Sicherheitstools diese Funktion verwenden, um Eingabeanforderungen für eine TCP-Sitzung zu identifizieren.

Feld Seriennummer enthält anfängliche Sequenznummer(Anfangssequenznummer), Feld Fenster - ursprüngliche Größe Empfangsfenster. Der einzige derzeit definierte TCP-Parameter ist die maximale Segmentgröße (wenn nicht angegeben, wird der Standardwert von 536 Bytes verwendet), die TCP zu empfangen erwartet. Dieser Wert belegt 32 Bit und ist üblicherweise in der Verbindungsanfrage im Feld vorhanden Optionen(Möglichkeit). Der TCP-Header mit dem MSS-Wert ist 24 Byte lang.

10.8.3 Verwendung von Header-Feldern in einer Antwort auf eine Verbindungsanfrage

In einer Grant-Antwort auf eine Verbindungsanforderung sind beide Flags (SYN und ACK) gleich 1. Das antwortende System gibt die Startsequenznummer im entsprechenden Feld und die Empfangsfenstergröße im Feld an Fenster. Maximale Größe Das Segment, das der Empfänger verwenden möchte, befindet sich normalerweise in der Antwort auf die Verbindungsanfrage (im Optionen). Dieser Wert kann vom Wert des Verbindungsanforderers abweichen, d. h. Es können zwei unterschiedliche Werte verwendet werden.

Eine Verbindungsanfrage kann abgelehnt werden, indem in der Antwort ein Reset-Flag (RST) mit dem Wert 1 angegeben wird.

10.8.4 Auswahl der Startsequenznummer

Die TCP-Spezifikation geht davon aus, dass beim Verbindungsaufbau jede Partei wählt anfängliche Sequenznummer(basierend auf dem aktuellen Wert des internen 32-Bit-Timers). Wie wird das gemacht?

Stellen wir uns vor, was passieren würde, wenn das System zusammenbricht. Nehmen wir an, dass der Benutzer kurz vor dem Absturz eine Verbindung geöffnet und eine kleine Datenmenge gesendet hat. Nach der Wiederherstellung merkt sich das System nichts mehr, was vor dem Absturz getan wurde, einschließlich bereits gestarteter Verbindungen und zugewiesener Portnummern. Der Benutzer stellt die Verbindung wieder her. Die Portnummern stimmen nicht mit den ursprünglichen Zuweisungen überein und einige davon werden möglicherweise bereits von anderen Verbindungen verwendet, die einige Sekunden vor dem Absturz hergestellt wurden.

Daher weiß der andere Teilnehmer am Ende der Verbindung möglicherweise nicht, dass sein Partner abgestürzt ist und anschließend wiederhergestellt wurde. All dies führt zu schwerwiegenden Störungen, insbesondere wenn lange Zeit bis die alten Daten durch das Netzwerk wandern und sich mit den Daten der neu erstellten Verbindung vermischen. Die Auswahl eines Starttimers mit einem Update (Neustart) beseitigt solche Probleme. Die alten Daten haben eine andere Nummerierung als der Sequenznummernbereich der neuen Verbindung. Wenn Hacker die Quell-IP-Adresse eines vertrauenswürdigen Hosts fälschen, versuchen sie, Zugriff auf Computer zu erhalten, indem sie in der Nachricht eine vorhersehbare Anfangssequenznummer angeben. Hierzu dient eine kryptografische Hashing-Funktion auf Basis interner Schlüssel der beste Weg um geschützte Startnummern auszuwählen.

10.8.5 Allgemeine Verwendungen von Feldern

Bei der Vorbereitung des TCP-Headers für die Übertragung wird im Feld die Sequenznummer des ersten Oktetts der übertragenen Daten angegeben Seriennummer(Sequenznummer).

In das Feld wird die Nummer des nächsten vom Verbindungspartner erwarteten Oktetts eingetragen Bestätigung(Bestätigungsnummer), wenn das ACK-Bit auf 1 gesetzt ist. Feld Fenster(Fenster) ist für die aktuelle Größe des Empfangsfensters vorgesehen. Dieses Feld enthält Anzahl der Bytes der Bestätigungsnummer, die empfangen werden können. Beachten Sie, dass dieser Wert eine präzise Steuerung des Datenflusses ermöglicht. Mit diesem Wert gibt der Peer den tatsächlichen Zustand des Empfangsfensters während der Austauschsitzung an.

Wenn eine Anwendung einen Push-Vorgang in TCP angibt, wird das PUSH-Flag auf 1 gesetzt. Das empfangende TCP MUSS auf dieses Flag antworten schnelle Lieferung Daten an die Anwendung, sobald der Absender sie versenden möchte.

Wenn das URGENT-Flag auf 1 gesetzt ist, impliziert es eine dringende Datenübertragung, und der entsprechende Zeiger muss auf das letzte Oktett der dringenden Daten verweisen. Eine typische Verwendung dringender Daten ist das Senden von Abbruch- oder Abbruchsignalen vom Terminal.

Dringende Daten werden oft aufgerufen Out-of-Band-Informationen(außerhalb der Bandbreite). Allerdings ist dieser Begriff ungenau. Dringende Daten werden im normalen TCP-Stream gesendet, obwohl einzelne Implementierungen möglicherweise über spezielle Mechanismen verfügen, um der Anwendung anzuzeigen, dass dringende Daten angekommen sind, und die Anwendung den Inhalt der dringenden Daten überprüfen muss, bevor alle Nachrichtenbytes angekommen sind.

Das RESET-Flag wird auf 1 gesetzt, wenn die Verbindung abnormal beendet werden soll. Das gleiche Flag wird in der Antwort gesetzt, wenn ein Segment eintrifft, das keiner der aktuellen TCP-Verbindungen zugeordnet ist.

Das FIN-Flag ist für Nachrichten zum Schließen der Verbindung auf 1 gesetzt.


10.8.6 Prüfsumme

Die IP-Prüfsumme gilt nur für den IP-Header, während die TCP-Prüfsumme für das gesamte Segment sowie den aus dem IP-Header erstellten Pseudo-Header berechnet wird. Bei der Berechnung der TCP-Prüfsumme hat das entsprechende Feld den Wert 0. In Abb. Abbildung 10.15 zeigt einen Pseudo-Header, der dem in einer UDP-Prüfsumme verwendeten stark ähnelt.


Reis. 10.15. Das Pseudo-Header-Feld ist in der TCP-Prüfsumme enthalten

Die TCP-Länge wird berechnet, indem die Länge des TCP-Headers zur Länge der Daten addiert wird. Die TCP-Prüfsumme ist obligatorisch, nicht wie UDP. Die Prüfsumme eines ankommenden Segments wird zunächst vom Empfänger berechnet und dann mit dem Inhalt des TCP-Header-Prüfsummenfelds verglichen. Stimmen die Werte nicht überein, wird das Segment verworfen.

10.9 Beispiel für ein TCP-Segment

Reis. 10.16, Betriebsprotokoll des Analysators Schnüffler von Network General ist eine Folge von TCP-Segmenten. Die ersten drei Segmente stellen die Verbindung zwischen Client und Server her Telnet. Das letzte Segment trägt 12 Byte Daten.


Reis. 10.16. Anzeige des TCP-Headers durch den Sniffer-Analysator

Analysator Schnüffler Konvertiert die meisten Werte in die Dezimalform. Allerdings werden die Flag-Werte hexadezimal ausgegeben. Ein Flag mit dem Wert 12 stellt 010010 dar. Die Prüfsumme wird ebenfalls hexadezimal ausgegeben.

10.10 Sitzungsunterstützung

10.10.1 Fensterprüfung

Ein schneller Sender und ein langsamer Empfänger können ein Empfangsfenster der Größe 0 Byte bilden. Dieses Ergebnis heißt das Fenster schließen(Fenster schließen). Wenn freier Speicherplatz zum Aktualisieren der Empfangsfenstergröße verfügbar wird, wird ACK verwendet. Geht eine solche Nachricht jedoch verloren, müssen beide Parteien auf unbestimmte Zeit warten.

Um diese Situation zu vermeiden, setzt der Absender speicherbarer Timer(Persistenz-Timer) beim Schließen des temporären Fensters. Der Timerwert ist das Zeitlimit für die erneute Übertragung. Nach Ablauf des Timers wird ein Segment an den Partner gesendet Fenstererkennung(Fensterprobe; einige Implementierungen umfassen auch Daten). Beim Prüfen sendet der Peer eine Bestätigung zurück, die den aktuellen Fensterstatus meldet.

Wenn das Fenster immer noch die Größe Null hat, wird der Wert des gespeicherten Timers verdoppelt. Dieser Vorgang wird wiederholt, bis der Timer das Maximum von 60 Sekunden erreicht. TCP sendet weiterhin alle 60 Sekunden Testnachrichten, bis das Fenster geöffnet wird, der Benutzer den Prozess beendet oder die Anwendung das Zeitlimit überschreitet.

10.11 Eine Sitzung beenden

10.11.1 Auszeit

Aufgrund eines fehlerhaften Gateways oder Links kann der Verbindungspartner abstürzen oder komplett unterbrochen werden. Um zu verhindern, dass Daten in TCP erneut übertragen werden, gibt es mehrere Mechanismen.

Wenn TCP den ersten Schwellenwert für die erneute Übertragung erreicht, weist es IP an, den ausgefallenen Router zu überprüfen, und informiert gleichzeitig die Anwendung darüber, dass ein Problem vorliegt. TCP leitet Daten weiter, bis der zweite Schwellenwert erreicht ist, bevor die Verbindung freigegeben wird.

Bevor dies geschieht, kann es natürlich sein, dass eine ICMP-Nachricht eintrifft, die darauf hinweist, dass das Ziel aus irgendeinem Grund nicht erreichbar ist. In einigen Implementierungen versucht TCP auch danach weiterhin, auf das Ziel zuzugreifen, bis das Timeout-Intervall abläuft (an diesem Punkt ist das Problem möglicherweise behoben). Als nächstes wird die Anwendung darüber informiert, dass der Zielpunkt nicht erreichbar ist.

Eine Anwendung kann ihr eigenes Zeitlimit für die Datenübermittlung festlegen und nach Ablauf dieses Intervalls ihre eigenen Vorgänge ausführen. Normalerweise wird die Verbindung beendet.

10.11.2 Verbindung aufrechterhalten

Wenn eine unvollständige Verbindung über einen längeren Zeitraum Daten weiterleiten muss, wird sie inaktiv. Während einer Zeit der Inaktivität kann das Netzwerk abstürzen oder physische Kommunikationsleitungen unterbrochen werden. Sobald das Netzwerk wieder betriebsbereit ist, tauschen die Partner weiterhin Daten aus, ohne die Kommunikationssitzung zu unterbrechen. Diese Strategie entsprach den Anforderungen des Verteidigungsministeriums.

Allerdings beansprucht jede Verbindung – ob aktiv oder inaktiv – viel Computerspeicher. Einige Administratoren müssen ungenutzte Ressourcen an Systeme zurückgeben. Daher sind viele TCP-Implementierungen in der Lage, eine Nachricht darüber zu senden Aufrechterhaltung der Verbindung(Keep-Alive), das inaktive Verbindungen testet. Solche Nachrichten werden regelmäßig an den Partner gesendet, um seine Existenz im Netzwerk zu überprüfen. Die Antwort sollte eine ACK-Nachricht sein. Die Verwendung von Keep-Alive-Nachrichten ist optional. Wenn das System über diese Fähigkeit verfügt, kann die Anwendung sie mit eigenen Mitteln außer Kraft setzen. Geschätzter Zeitraum Default Der Verbindungswartungs-Timeout beträgt satte zwei Stunden!

Denken Sie daran, dass eine Anwendung ihren eigenen Timer einstellen kann, nach dem sie auf ihrer eigenen Ebene entscheidet, ob die Verbindung beendet wird.

10.12 Leistung

Wie effizient ist TCP? Die Ressourcenleistung wird von vielen Faktoren beeinflusst, die wichtigsten sind Speicher und Bandbreite (siehe Abbildung 10.17).


Reis. 10.17. TCP-Leistungsfaktoren

Die Bandbreite und Latenz des verwendeten physischen Netzwerks schränkt den Durchsatz erheblich ein. Eine schlechte Qualität der Datenweiterleitung führt zu einer großen Menge verworfener Datagramme, was zu erneuten Übertragungen führt und folglich die Bandbreiteneffizienz verringert.

Der Empfänger muss ausreichend Pufferspeicher bereitstellen, damit der Sender Daten ohne Unterbrechung senden kann. Dies ist besonders wichtig für Netzwerke mit hoher Latenz, bei denen zwischen dem Senden von Daten und dem Empfang einer ACK (und beim Aushandeln der Fenstergröße) ein langer Zeitabstand liegt. Um einen stetigen Datenfluss von der Quelle aufrechtzuerhalten, muss auf der Empfängerseite ein Fenster vorhanden sein, das mindestens der Größe des Produkts aus Bandbreite und Latenz entspricht.

Wenn die Quelle beispielsweise Daten mit einer Rate von 10.000 Bytes/s senden kann und die ACK zwei Sekunden benötigt, um zurückzukehren, muss die andere Seite ein Empfangsfenster mit einer Größe von mindestens 20.000 Bytes bereitstellen, andernfalls funktioniert der Datenfluss nicht kontinuierlich sein. Ein 10.000 Byte großer Empfangspuffer halbiert den Durchsatz.

Ein weiterer wichtiger Faktor für die Leistung ist die Fähigkeit des Hosts, auf Ereignisse mit hoher Priorität zu reagieren und diese schnell auszuführen Kontextwechsel, d.h. Schließen Sie einige Vorgänge ab und wechseln Sie zu anderen. Der Host kann interaktiv mehrere lokale Benutzer stapelweise unterstützen Hintergrundprozesse und Dutzende gleichzeitiger Kommunikationsverbindungen. Mit der Kontextumschaltung können Sie alle diese Vorgänge ausführen und gleichzeitig die Belastung des Systems verbergen. Implementierungen, die TCP/IP in den Betriebssystemkernel integrieren, können die Belastung durch die Verwendung von Kontextwechseln erheblich reduzieren.

Ressourcen zentraler Prozessor Für die TCP-Header-Verarbeitung sind Computer erforderlich. Wenn der Prozessor Prüfsummen nicht schnell berechnen kann, führt dies zu einer Verringerung der Geschwindigkeit der Datenübertragung über das Netzwerk.

Darüber hinaus sollten Entwickler darauf achten, die Konfiguration der TCP-Einstellungen zu vereinfachen, damit der Netzwerkadministrator sie entsprechend seinen lokalen Anforderungen konfigurieren kann. Beispielsweise wird die Möglichkeit, die Puffergröße an die Netzwerkbandbreite und Latenz anzupassen, die Leistung erheblich verbessern. Leider berücksichtigen viele Implementierungen dieses Problem nicht ausreichend und programmieren die Kommunikationsparameter streng.

Nehmen wir an, dass die Netzwerkumgebung perfekt ist: Es sind genügend Ressourcen vorhanden und der Kontextwechsel erfolgt schneller als Cowboys, die ihre Revolver zücken. Wird eine hervorragende Leistung erzielt?

Nicht immer. Auch die Qualität der TCP-Softwareentwicklung ist wichtig. Im Laufe der Jahre wurden viele Leistungsprobleme in verschiedenen TCP-Implementierungen diagnostiziert und behoben. Man kann davon ausgehen, dass es das Beste wäre Software, konform mit RFC 1122, der die Anforderungen für die Kommunikationsschicht von Internet-Hosts definiert.

Ebenso wichtig ist die Ausnahme und die Verwendung von Jacobson-, Kern- und Partridge-Algorithmen (diese interessanten Algorithmen werden weiter unten besprochen).

Softwareentwickler können erhebliche Vorteile erzielen, indem sie Programme erstellen, die unnötige Übertragungen kleiner Datenmengen verhindern und über integrierte Timer verfügen, um Netzwerkressourcen freizugeben, die derzeit nicht verwendet werden.

10.13 Algorithmen zur Leistungsverbesserung

Als Nächstes lernen wir den recht komplexen Teil von TCP kennen und betrachten Mechanismen zur Leistungssteigerung und Lösung von Problemen mit reduziertem Durchsatz. In diesem Abschnitt werden die folgenden Probleme behandelt:

Langsamer Start(langsamer Start) verhindert die Verwendung eines großen Anteils Netzwerktraffic für eine neue Sitzung, was zu einem Overhead führen kann.

■ Heilung von „ahnungsloses Fenster“-Syndrom(Silly-Window-Syndrom) verhindert, dass schlecht gestaltete Anwendungen das Netzwerk mit Nachrichten überlasten.

Verzögerte Bestätigung(verzögertes ACK) reduziert die Überlastung, indem die Anzahl unabhängiger Bestätigungsnachrichten für die Datenweiterleitung reduziert wird.

Berechnetes Zeitlimit für die erneute Übertragung(Computing Retransmission Timeout) basiert auf der Aushandlung der tatsächlichen Sitzungszeit und reduziert so die Anzahl unnötiger Neuübertragungen, verursacht jedoch keine großen Verzögerungen für wirklich notwendige Datenaustausche.

■ Unterdrückung der TCP-Weiterleitung, wenn Überlastungen In einem Netzwerk können Router in ihren ursprünglichen Modus zurückkehren und Netzwerkressourcen über alle Sitzungen hinweg gemeinsam nutzen.

■ Versand doppelte ACKs(doppelte ACK) Wenn ein Segment außerhalb der Reihenfolge empfangen wird, können Peers erneut übertragen, bevor eine Zeitüberschreitung auftritt.

10.13.1 Langsamer Start

Wenn Sie zu Hause alle elektrischen Haushaltsgeräte gleichzeitig einschalten, kommt es zu einer Überlastung. elektrisches Netzwerk. In Computernetzwerken langsamer Start verhindert das Durchbrennen von Netzsicherungen.

Eine neue Verbindung, die sofort große Datenmengen in ein bereits ausgelastetes Netzwerk sendet, kann zu Problemen führen. Die Idee eines langsamen Starts besteht darin, sicherzustellen, dass eine neue Verbindung erfolgreich gestartet wird, während gleichzeitig die Datenübertragungsrate entsprechend der tatsächlichen Netzwerklast langsam erhöht wird. Der Absender ist durch die Größe des Ladefensters begrenzt, nicht durch das größere Empfangsfenster.

Fenster laden(Überlastungsfenster) beginnt mit einer Größe von 1 Segment. Für jedes Segment mit erfolgreich empfangenem ACK wird die Ladefenstergröße um 1 Segment erhöht, bis sie kleiner als das Empfangsfenster bleibt. Wenn das Netzwerk nicht überlastet ist, erreicht das Ladefenster nach und nach die Größe des Empfangsfensters. Unter normalen Weiterleitungsbedingungen sind die Größen dieser Fenster gleich.

Beachten Sie, dass ein langsamer Start nicht so langsam ist. Nach der ersten ACK beträgt die Größe des Ladefensters 2 Segmente, und nach erfolgreichem Empfang der ACK für zwei Segmente kann die Größe auf 8 Segmente ansteigen. Mit anderen Worten: Die Fenstergröße nimmt exponentiell zu.

Nehmen wir an, dass anstelle des Empfangs einer Bestätigung eine Zeitüberschreitung auftritt. Das Verhalten des Lastfensters in diesem Fall wird weiter unten erläutert.

10.13.2 Clueless-Window-Syndrom

Bei den ersten TCP/IP-Implementierungen stießen Entwickler auf das Phänomen „ahnungsloses Fenster“-Syndrom(Silly-Window-Syndrom – SWS), das recht häufig auftrat. Um die ablaufenden Ereignisse zu verstehen, stellen Sie sich das folgende Szenario vor, das zu unerwünschten Folgen führt, aber durchaus möglich ist:

1. Die sendende Anwendung sendet Daten schnell.

2. Die empfangende Anwendung liest 1 Byte Daten aus dem Eingabepuffer (d. h. langsam).

3. Der Eingabepuffer füllt sich nach dem Lesen schnell.

4. Die empfangende Anwendung liest 1 Byte und TCP sendet eine ACK mit der Bedeutung „Ich habe freien Speicherplatz für 1 Byte Daten.“

5. Die sendende Anwendung sendet ein 1-Byte-TCP-Paket über das Netzwerk.

6. Der empfangende TCP sendet eine Bestätigung mit der Bedeutung „Danke. Ich habe das Paket erhalten und habe keinen freien Speicherplatz mehr.“

7. Die empfangende Anwendung liest erneut 1 Byte und sendet eine Bestätigung, und der gesamte Vorgang wiederholt sich.

Eine langsam empfangende Anwendung wartet lange auf das Eintreffen von Daten und verschiebt die empfangenen Informationen ständig an den linken Rand des Fensters, wodurch ein völlig nutzloser Vorgang ausgeführt wird, der zusätzlichen Datenverkehr im Netzwerk erzeugt.

Reale Situationen sind natürlich nicht so extrem. Ein schneller Sender und ein langsamer Empfänger tauschen kleine (im Verhältnis zur maximalen Segmentgröße) Datenstücke aus und schalten ein nahezu volles Empfangsfenster um. In Abb. Abbildung 10.18 zeigt die Bedingungen für das Auftreten des „Dummfenster“-Syndroms.


Reis. 10.18. Pufferempfangsfenster mit sehr kleinem freien Speicherplatz

Dieses Problem zu lösen ist nicht schwierig. Sobald das Empfangsfenster auf eine Länge kleiner als diese Zielgröße reduziert wird, beginnt TCP, den Absender zu täuschen. In dieser Situation sollte TCP den Absender nicht informieren zusätzlich Fensterbereich, wenn die empfangende Anwendung Daten in kleinen Blöcken aus dem Puffer liest. Stattdessen müssen Sie die freigegebenen Ressourcen vor dem Absender geheim halten, bis genügend davon vorhanden sind. Es wird eine einzelne Segmentgröße empfohlen, es sei denn, der gesamte Eingabepuffer speichert ein einzelnes Segment (im letzteren Fall wird eine halbe Puffergröße verwendet). Die Zielgröße, die TCP melden sollte, kann wie folgt ausgedrückt werden:

Minimum (1/2 Eingabepuffer, maximale Segmentgröße)

TCP beginnt zu lügen, wenn die Fenstergröße kleiner als diese Größe wird, und sagt die Wahrheit, wenn die Fenstergröße nicht kleiner als der aus der Formel erhaltene Wert ist. Beachten Sie, dass für den Absender kein Schaden entsteht, da die empfangende Anwendung ohnehin nicht in der Lage wäre, einen Großteil der erwarteten Daten zu verarbeiten.

Die vorgeschlagene Lösung lässt sich im oben diskutierten Fall leicht mit einer ACK-Ausgabe für jedes der empfangenen Bytes verifizieren. Die gleiche Methode eignet sich auch für den Fall, dass der Eingabepuffer mehrere Segmente speichern kann (was in der Praxis häufig der Fall ist). Der schnelle Absender füllt den Eingabepuffer, aber der Empfänger zeigt an, dass er keinen freien Platz für die Informationen hat und öffnet diese Ressource erst, wenn ihre Größe das gesamte Segment erreicht.

10.13.3 Nagle-Algorithmus

Der Absender muss unabhängig vom Empfänger den Versand sehr kurzer Segmente vermeiden, indem er vor dem Versand Daten ansammelt. Der Algorithmus von Nagle implementiert eine sehr einfache Idee, mit der Sie die Anzahl der über das Netzwerk gesendeten kurzen Datagramme reduzieren können.

Der Algorithmus empfiehlt, die Datenweiterleitung (und das Pushen) zu verzögern, während auf eine Bestätigung von zuvor übertragenen Daten gewartet wird. Akkumulierte Daten werden gesendet, nachdem ein ACK für eine zuvor gesendete Information empfangen wurde, oder nachdem Daten empfangen wurden, die in der Menge eines vollständigen Segments gesendet werden sollen, oder nach Ablauf einer Zeitüberschreitung. Dieser Algorithmus sollte nicht für Echtzeitanwendungen verwendet werden, die Daten so schnell wie möglich senden müssen.

10.13.4 Verzögerte Bestätigung

Ein weiterer Mechanismus zur Leistungsverbesserung ist die ACK-Verzögerungsmethode. Durch die Reduzierung der Anzahl der ACKs verringert sich die Bandbreite, die zum Weiterleiten von anderem Datenverkehr verwendet werden kann. Wenn der TCP-Peer das Senden der ACK leicht verzögert, dann:

■ Mehrere Segmente können mit einem einzigen ACK bestätigt werden.

■ Die empfangende Anwendung kann innerhalb des Timeout-Intervalls eine gewisse Datenmenge empfangen, d. h. Das ACK kann den Ausgabeheader enthalten und erfordert nicht die Generierung einer separaten Nachricht.

Um Verzögerungen beim Senden eines Streams voller Segmente zu vermeiden (z. B. beim Austausch von Dateien), sollte für mindestens jedes zweite vollständige Segment eine Bestätigung gesendet werden.

Viele Implementierungen verwenden ein Timeout von 200 ms. Eine verspätete ACK senkt jedoch nicht den Wechselkurs. Wenn ein kurzes Segment eintrifft, ist im Eingabepuffer noch genügend freier Speicherplatz für den Empfang neuer Daten vorhanden und der Absender kann mit dem Senden fortfahren (außerdem ist das erneute Senden normalerweise viel langsamer). Wenn ein ganzes Segment eintrifft, müssen Sie in derselben Sekunde mit einer ACK-Nachricht darauf antworten.

10.13.5 Zeitüberschreitung bei erneuter Übertragung

Nach dem Senden des Segments stellt TCP einen Timer ein und überwacht das Eintreffen der ACK. Wenn innerhalb des Timeout-Zeitraums kein ACK empfangen wird, überträgt TCP das Segment erneut (Relay). Doch wie lang sollte die Auszeit sein?

Wenn es zu kurz ist, überschwemmt der Absender das Netzwerk, indem er unnötige Segmente weiterleitet, die bereits gesendete Informationen duplizieren. Eine zu große Zeitüberschreitung verhindert die schnelle Reparatur von Segmenten, die während der Weiterleitung tatsächlich zerstört werden, was den Durchsatz verringert.

Wie wählt man den richtigen Timeout-Zeitraum? Wert für hohe Geschwindigkeit geeignet lokales Netzwerk, ist für Remote-Verbindungen mit vielen Treffern nicht geeignet. Das bedeutet, dass der Grundsatz „ein Wert für alle Bedingungen“ eindeutig ungeeignet ist. Darüber hinaus können sich die Netzwerkbedingungen auch bei einer bestehenden spezifischen Verbindung ändern und Verzögerungen können zunehmen oder abnehmen.

Jacobson-, Kern- und Partridge-Algorithmen (in den Artikeln beschrieben). , Van Jacobson und Verbesserung der Round-Trip-Zeitschätzungen in zuverlässigen Transportprotokollen, Karn und Partridge) ermöglichen TCP die Anpassung an sich ändernde Netzwerkbedingungen. Diese Algorithmen werden für die Verwendung in neuen Implementierungen empfohlen. Wir werden sie im Folgenden kurz betrachten.

Der gesunde Menschenverstand besagt, dass die beste Grundlage für die Schätzung der korrekten Timeout-Zeit für eine bestimmte Verbindung die Überwachung ist Zykluszeit(Umlaufzeit) als Intervall zwischen dem Senden von Daten und dem Empfang einer Empfangsbestätigung.

Gute Lösungen Für die folgenden Größen können aus Basisstatistiken (siehe Abbildung 10.19) gewonnen werden, die bei der Berechnung der Timeout-Zeit helfen. Sie sollten sich jedoch nicht auf Durchschnittswerte verlassen, da mehr als die Hälfte der Schätzungen über dem statistischen Durchschnitt liegen wird. Durch die Berücksichtigung einiger Ausreißer können wir bessere Schätzungen erhalten, die die Normalverteilung berücksichtigen und die übermäßig lange Wartezeit für die erneute Übertragung reduzieren.


Reis. 10.19. Verteilung der Zykluszeiten

Es sind keine umfangreichen Berechnungen erforderlich, um formale mathematische Schätzungen der Abweichungen zu erhalten. Sie können ziemlich grobe Schätzungen verwenden, die auf dem absoluten Wert der Differenz zwischen dem letzten Wert und der durchschnittlichen Schätzung basieren:

Letzte Abweichung = | Letzter Zyklus - Durchschnitt |

Um den korrekten Timeout-Wert zu berechnen, muss ein weiterer Faktor berücksichtigt werden: die Änderung der Zykluszeit aufgrund der aktuellen Netzwerkbedingungen. Was in letzter Minute online passiert, ist wichtiger als das, was vor einer Stunde passiert ist.

Nehmen wir an, dass wir den Zyklusdurchschnitt für eine sehr lange Sitzung berechnen. Lassen Sie das Netzwerk zunächst leicht belastet sein und wir haben 1000 kleine Werte identifiziert, aber dann kam es zu einem Anstieg des Datenverkehrs mit einem deutlichen Anstieg der Latenz.

Wenn beispielsweise 1000 Werte einen statistischen Durchschnitt von 170 Einheiten ergeben würden, dann aber 50 Werte mit einem Durchschnitt von 282 gemessen wurden, dann wäre der aktuelle Durchschnitt:

170×1000/1050 + 282×50/1050 = 175

Ein vernünftigerer Wert wäre geglättete Zykluszeit(Smoothed Round-Trip Time – SRTT), das die Priorität späterer Werte berücksichtigt:

Neue SRTT = (1 – α)×(alte SRTT) + α×Letzter Zykluswert

Der Wert von α liegt zwischen 0 und 1. Erhöhen Sie a Dadurch ergibt sich ein größerer Einfluss der aktuellen Zykluszeit auf den geglätteten Mittelwert. Weil Computer durch Verschiebung schnell durch Zweierpotenzen dividieren können Binärzahlen rechts wird α immer auf (1/2) n (normalerweise 1/8) gesetzt, also:

Neue SRTT = 7/8×Alte SRTT + 1/8×Letzte Zykluszeit

Tabelle 10.2 zeigt, wie sich die Formel für SRTT anpasst Vorhandener Wert Ein SRTT von 230, wenn eine Änderung der Netzwerkbedingungen zu einer progressiven Erhöhung der Zykluszeit führt (vorausgesetzt, es tritt kein Timeout auf). Die Werte in Spalte 3 werden als Werte in Spalte 1 für die nächste Zeile der Tabelle verwendet (also wie beim alten SRTT).


Tabelle 10.2 Berechnung der geglätteten Zykluszeit

Alter SRTT Neueste RTT (7/8)×(altes SRTT) + (1/8)×(RTT)
230.00 294 238.00
238.00 264 241.25
241.25 340 253.59
253.59 246 252.64
252.64 201 246.19
246.19 340 257.92
257.92 272 259.68
259.68 311 266.10
266.10 282 268.09
268.09 246 265.33
265.33 304 270.16
270.16 308 274.89
274.89 230 269.28
269.28 328 276.62
276.62 266 275.29
275.29 257 273.00
273.00 305 277.00

Nun stellt sich die Frage nach der Auswahl eines Werts für das Zeitlimit für die erneute Übertragung. Die Analyse der Zykluszeitwerte zeigt eine deutliche Abweichung dieser Werte vom aktuellen Durchschnittswert. Es ist sinnvoll, die Größe der Abweichungen zu begrenzen. Ein guter Wert für das Neuübertragungs-Timeout (in den RFC-Standards wird dieser Wert als Retransmission TimeOut – RTO bezeichnet) wird durch die folgende Formel mit einer SDEV-Einschränkung (Smoothed Deviation) angegeben:

T = Neuübertragungs-Timeout = SRTT + 2×SDEV

T = SRTT + 4×SDEV

Um SDEV zu berechnen, ermitteln Sie zunächst den Absolutwert der aktuellen Abweichung:

DEV = | Letzte Zykluszeit - altes SRTT |

Um den letztgenannten Wert zu berücksichtigen, wird dann die Glättungsformel verwendet:

Neues SDEV = 3/4×altes SDEV + 1/4×DEV

Eine Frage bleibt: Welche Anfangswerte sollen angenommen werden? Empfohlen:

Anfängliches Timeout = 3 s

Anfänglicher SRTT = 0

Anfänglicher SDEV = 1,5 s

Van Jacobson hat einen schnellen Algorithmus definiert, der das Timeout für die erneute Datenübertragung sehr effizient berechnet.

10.13.6 Statistikbeispiel

Wie erfolgreich wird das oben berechnete Timeout sein? Bei der Implementierung dieses Werts konnten deutliche Leistungsverbesserungen beobachtet werden. Ein Beispiel wären Teamstatistiken netstat, im System empfangen Tiger- ein Internetserver, auf den viele Hosts aus der ganzen Welt zugreifen.


1510769 Pakete (314955304 Bytes) wurden nacheinander empfangen

System Tiger Weniger als 2,5 % der TCP-Datensegmente wurden erneut übertragen. Von eineinhalb Millionen eingehenden Datensegmenten (der Rest sind reine ACK-Nachrichten) wurden nur 0,6 % dupliziert. Dabei ist zu berücksichtigen, dass die Höhe der Verluste in den Eingangsdaten in etwa der Höhe der Ausgangssegmente entspricht. Somit macht der verschwenderische Neuübertragungsverkehr etwa 0,6 % des Gesamtverkehrs aus.

10.13.7 Berechnungen nach erneutem Senden

Die oben dargestellten Formeln verwenden die Zykluszeit als Intervall zwischen dem Senden eines Segments und dem Empfang einer Empfangsbestätigung. Nehmen wir jedoch an, dass innerhalb des Timeout-Zeitraums keine Bestätigung empfangen wird und die Daten erneut gesendet werden müssen.

Der Kern-Algorithmus geht davon aus, dass die Zykluszeit in diesem Fall nicht verändert werden sollte. Aktueller geglätteter Zykluszeitwert und geglättete Abweichung behalten ihre Werte bei, bis die Bestätigung eingeht, ein bestimmtes Segment weiterzuleiten, ohne es erneut zu senden. Ab diesem Zeitpunkt werden die Berechnungen auf Basis der gespeicherten Werte und neuer Messungen fortgesetzt.

10.13.8 Aktionen nach erneuter Übertragung

Aber was passiert, bevor die Bestätigung eintrifft? Nach der erneuten Übertragung ändert sich das TCP-Verhalten radikal, hauptsächlich aufgrund von Datenverlusten aufgrund einer Netzwerküberlastung. Daher lautet die Antwort auf das erneute Senden der Daten:

■ Reduzierte Neuübertragungsrate

■ Bekämpfen Sie Netzwerküberlastungen, indem Sie den Gesamtverkehr reduzieren

10.13.9 Exponentielles Bremsen

Nach der erneuten Übertragung wird das Timeout-Intervall verdoppelt. Was passiert jedoch, wenn der Timer erneut überläuft? Die Daten werden erneut gesendet und der Zeitraum für die erneute Übertragung verdoppelt sich erneut. Dieser Vorgang wird aufgerufen exponentielles Bremsen(exponentielles Backoff).

Wenn der Netzwerkfehler weiterhin auftritt, verdoppelt sich die Timeout-Zeit, bis der voreingestellte Maximalwert erreicht ist (normalerweise 1 Minute). Nach einer Zeitüberschreitung kann nur noch ein Segment gesendet werden. Ein Timeout tritt auch auf, wenn der voreingestellte Wert für die Anzahl der Datenübertragungen ohne Empfang eines ACK überschritten wird.

10.13.10 Reduzierung der Überlastung durch Reduzierung der über das Netzwerk gesendeten Daten

Die Reduzierung der gesendeten Datenmenge ist etwas komplexer als die oben diskutierten Mechanismen. Es beginnt zu funktionieren, genau wie der bereits erwähnte langsame Start. Da es jedoch eine Grenze für das Verkehrsaufkommen gibt, die zunächst zu Problemen führen kann, verlangsamt sich die Austauschgeschwindigkeit aufgrund der Vergrößerung des Lastfensters für ein Segment tatsächlich. Sie müssen die Grenzwerte festlegen, um die Sendegeschwindigkeit tatsächlich zu reduzieren. Zunächst wird die Gefahrenschwelle berechnet:

Grenze – 1/2 Minimum (aktuelles Lastfenster, Partner-Empfangsfenster)

Wenn der resultierende Wert mehr als zwei Segmente umfasst, wird er als Grenze verwendet. Andernfalls wird die Rahmengröße auf zwei Segmente festgelegt. Der vollständige Wiederherstellungsalgorithmus erfordert:

■ Stellen Sie die Größe des Ladefensters auf ein Segment ein.

■ Erhöhen Sie für jede empfangene Bestätigung die Größe des Ladefensters um ein Segment, bis die Grenze erreicht ist (ähnlich wie beim langsamen Startmechanismus).

■ Fügen Sie anschließend mit jedem empfangenen ACK einen kleineren Wert zum Lastfenster hinzu, der basierend auf der Anstiegsrate pro Segment für die Zykluszeit ausgewählt wird (der Anstieg wird als MSS/N berechnet, wobei N die Größe des Lastfensters ist). in Segmenten).

Das ideale Szenario kann eine vereinfachte Darstellung der Funktionsweise des Wiederherstellungsmechanismus bieten. Nehmen wir an, dass das Empfangsfenster des Partners (und das aktuelle Ladefenster) vor der Erkennung des Timeouts eine Größe von 8 Segmenten hatte und die Grenze als 4 Segmente definiert wurde. Wenn die empfangende Anwendung sofort Daten aus dem Puffer liest, bleibt die Größe des Empfangsfensters 8 Segmente.

■ 1 Segment wird gesendet (Ladefenster = 1 Segment).

■ ACK empfangen – 2 Segmente werden gesendet.

■ ACK für 2 Segmente empfangen – 4 Segmente werden gesendet (Grenze erreicht).

■ ACK für 4 Segmente empfangen. Es werden 5 Segmente gesendet.

■ ACK für 5 Segmente empfangen. Es werden 6 Segmente gesendet.

■ ACK für 6 Segmente empfangen. Es werden 7 Segmente gesendet.

■ ACK für 7 Segmente empfangen. Es werden 8 Segmente gesendet (das Ladefenster ist wiederum gleich groß wie das Empfangsfenster).

Da für die erneute Übertragung aufgrund einer Zeitüberschreitung eine Bestätigung des Empfangs aller gesendeten Daten erforderlich ist, wird der Vorgang fortgesetzt, bis das Ladefenster die Größe des Empfangsfensters erreicht. Die stattfindenden Ereignisse sind in Abb. dargestellt. 10.20. Die Fenstergröße nimmt exponentiell zu, verdoppelt sich während der langsamen Startphase und nimmt linear zu, sobald die Grenze erreicht ist.


Reis. 10.20. Begrenzung der Weiterleitungsgeschwindigkeit bei Überlastung

10.13.11 Doppelte ACKs

Einige Implementierungen verwenden eine optionale Funktion namens Schnelles erneutes Senden(Fast Retransmit) – um das erneute Senden von Daten unter bestimmten Bedingungen zu beschleunigen. Die Grundidee besteht darin, dass der Empfänger zusätzliche ACKs sendet, die auf eine Lücke in den empfangenen Daten hinweisen.

Wenn ein Segment außerhalb der Reihenfolge empfangen wird, sendet der Empfänger ein ACK zurück, das auf das erste Byte verweist verloren Daten (siehe Abbildung 10.21).


Reis. 10.21. Doppelte ACKs

Der Absender überträgt die Daten nicht sofort erneut, da IP normalerweise Daten ohne Sendesequenz an den Empfänger senden kann. Wenn jedoch mehrere zusätzliche doppelte Daten-ACKs empfangen werden (z. B. drei), wird das fehlende Segment gesendet, ohne auf den Ablauf des Timeouts zu warten.

Beachten Sie, dass jede doppelte ACK den Empfang eines Datensegments anzeigt. Mehrere doppelte ACKs weisen darauf hin, dass das Netzwerk in der Lage ist, eine ausreichende Datenmenge zu liefern und daher nicht übermäßig belastet ist. Als Teil des Gesamtalgorithmus wird eine kleine Reduzierung der Größe des Lastfensters durchgeführt, wenn der Netzwerkverkehr tatsächlich zunimmt. In diesem Fall wird der Prozess der radikalen Größenänderung bei der Wiederherstellung der Arbeit nicht angewendet.

Laut Norm Host-Anforderungen(Hostanforderungen) TCP muss beim Löschen der Quelle den gleichen langsamen Start wie oben beschrieben durchführen. Diese Nachricht ist jedoch weder zielgerichtet noch effektiv, da die Verbindung, die die Nachricht empfängt, möglicherweise nicht viel Datenverkehr generiert. Aktuelle Spezifikation Router-Anforderungen(Router-Anforderungen) gibt an, dass Router sollte nicht Senden Sie Nachrichten zur Quellenunterdrückung.

13.10.13 TCP-Statistiken

Schauen wir uns abschließend die statistischen Meldungen des Teams an netstat, um zu sehen, wie viele der oben beschriebenen Mechanismen wirken.

Segmente werden Pakete genannt.
879137 Datenpakete (226966295 Bytes)
21815 Datenpakete (8100927 Bytes) erneut übertragen
Neuversand.
132957 Nur-Ack-Pakete (104216 verzögert)
Beachten wir eine große Zahl

verzögerte ACK.

Fensteröffnung prüfen

Nullgröße.

Dies sind SYN- und FIN-Nachrichten.
762469 Bestätigungen (für 226904227 Bytes)
Signal über ankommende Pakete

ausser der Reihe.

1510769 Pakete (314955304 Bytes)
9006 vollständig doppelte Pakete (867042 Bytes)
Timeout-Ergebnis mit real

Datenlieferung.

74 Pakete mit etwas Dup. Daten (12193 Bytes kopiert)
Für mehr Effizienz

Einige Daten wurden neu verpackt, um beim erneuten Senden zusätzliche Bytes einzuschließen.

13452 Pakete außerhalb der Reihenfolge (2515087 Bytes)
530 Pakete (8551 Byte) Daten nach dem Fenster
Vielleicht waren es diese Daten

in den klingenden Nachrichten enthalten.

Nach dem Schließen wurden 402 Pakete empfangen
Dies sind aufeinanderfolgende Wiederholungen

Senden.

108 wegen fehlerhafter Prüfsummen verworfen
Ungültige TCP-Prüfsumme.
0 wird für fehlerhafte Header-Offset-Felder verworfen
7 verworfen, da Paket zu kurz
14677 Verbindungen hergestellt (einschließlich akzeptiert)
18929 Verbindungen geschlossen (einschließlich 643 Verbindungen)
4100 embryonale Verbindungen wurden abgebrochen
572187 Segmente aktualisiertes RTT (von 587397 Versuchen)
Fehlgeschlagene Änderungsversuche

Zykluszeit, da das ACK nicht vor Ablauf des Timeouts eintraf,

26 Verbindungen wurden durch Rexmit-Timeout unterbrochen
Anschließend erfolglose Versuche

erneut senden, was auf einen Verbindungsverlust hinweist.

Zeitüberschreitungen beim Prüfen

Nullfenster.

Zeitüberschreitungen bei der Überprüfung

unterbrochene Verbindung.

472 Verbindungen wurden durch Keepalive unterbrochen

10.14 Einhaltung der Entwickleranforderungen

Der aktuelle TCP-Standard verlangt von Implementierungen, dass sie sich beim Initialisieren einer Verbindung strikt an das langsame Startverfahren halten und die Kern- und Jacobson-Algorithmen zum Schätzen des Zeitlimits für das erneute Senden von Daten und zur Lastkontrolle verwenden. Tests haben gezeigt, dass diese Mechanismen zu erheblichen Leistungsverbesserungen führen.

Was passiert, wenn Sie ein System installieren, das diese Standards nicht strikt einhält? Es kann seinen eigenen Benutzern keine ausreichende Leistung bieten und ist ein schlechter Nachbar für andere Systeme im Netzwerk, was eine Wiederherstellung verhindert normale Operation nach vorübergehender Überlastung und übermäßigem Datenverkehr, der dazu führt, dass Datagramme verworfen werden.

10.15 Hindernisse für die Produktivität

TCP hat seine Flexibilität durch den Betrieb in Netzwerken mit Übertragungsraten von Hunderten oder Millionen Bits pro Sekunde unter Beweis gestellt. Dieses Protokoll hat in modernen lokalen Netzwerken mit Ethernet-, Token-Ring- und Fiber Distributed Data Interface (FDDI)-Topologien sowie für langsame Kommunikationsverbindungen oder Fernverbindungen (ähnlich Satellitenverbindungen) gute Ergebnisse erzielt.

TCP ist darauf ausgelegt, auf extreme Bedingungen wie Netzwerküberlastung zu reagieren. Allerdings in aktuelle Version Das Protokoll verfügt über Funktionen, die die Leistung vielversprechender Technologien einschränken, die eine Bandbreite von Hunderten oder Tausenden Megabyte bieten. Um die damit verbundenen Probleme zu verstehen, betrachten Sie ein einfaches (wenn auch unrealistisches) Beispiel.

Angenommen, Sie möchten beim Verschieben einer Datei zwischen zwei Systemen einen kontinuierlichen Austausch so effizient wie möglich durchführen. Nehmen wir an, dass:

■ Die maximale Größe des Empfängersegments beträgt 1 KB.

■ Empfangsfenster – 4 KB.

Die Bandbreite ermöglicht das Senden von zwei Segmenten in 1 s.

■ Die empfangende Anwendung verbraucht Daten, sobald sie ankommen.

■ ACK-Nachrichten kommen nach 2 s an.

Der Absender ist in der Lage, kontinuierlich Daten zu senden. Wenn das für das Fenster zugewiesene Volumen voll ist, kommt schließlich eine ACK, die das Senden eines weiteren Segments ermöglicht:

Nach 2 s:

EMPFANGEN SIE DIE BESTÄTIGUNG VON SEGMENT 1, KÖNNEN SEGMENT 5 SENDEN.
EMPFANGEN SIE DIE BESTÄTIGUNG VON SEGMENT 2, KÖNNEN SEGMENT 6 SENDEN.
EMPFANGEN SIE DIE BESTÄTIGUNG VON SEGMENT 3, KÖNNEN SEGMENT 7 SENDEN.
EMPFANGEN SIE DIE BESTÄTIGUNG VON SEGMENT 4, KÖNNEN SEGMENT 8 SENDEN.

Nach weiteren 2 s:

EMPFANGEN SIE DIE BESTÄTIGUNG VON SEGMENT 5, KÖNNEN SEGMENT 9 SENDEN.

Wenn das Empfangsfenster nur 2 KB groß wäre, müsste der Absender jede zweite Sekunde warten, bevor er die nächsten Daten sendet. Um einen kontinuierlichen Datenstrom zu halten, muss das Empfangsfenster tatsächlich mindestens Folgendes umfassen:

Fenster = Bandbreite×Zykluszeit

Obwohl das Beispiel etwas übertrieben ist (um einfachere Zahlen zu liefern), kann ein kleines Fenster bei Satellitenverbindungen mit hoher Latenz zu Problemen führen.

Schauen wir uns nun an, was mit Hochgeschwindigkeitsverbindungen passiert. Wenn beispielsweise die Bandbreite und die Weiterleitungsrate bei 10 Millionen Bits pro Sekunde gemessen werden, die Zykluszeit aber 100 ms (1/10 Sekunde) beträgt, dann muss das Empfangsfenster für einen kontinuierlichen Stream mindestens 1.000.000 Bits speichern, d. h. . 125.000 Byte. Aber die größte Zahl, die in das Header-Feld für ein TCP-Empfangsfenster geschrieben werden kann, ist 65.536.

Ein weiteres Problem tritt auf, wenn hohe Geschwindigkeiten Umtausch, da die Seriennummern sehr schnell ausgehen. Wenn die Verbindung Daten mit einer Geschwindigkeit von 4 GB/s übertragen kann, müssen die Sequenznummern innerhalb jeder Sekunde aktualisiert werden. Es wird keine Möglichkeit geben, zwischen alten doppelten Datagrammen, die bei der Übertragung über das Internet um mehr als eine Sekunde verzögert wurden, und neuen neuen Daten zu unterscheiden.

Es werden aktiv neue Forschungsarbeiten durchgeführt, um TCP/IP zu verbessern und die oben genannten Hindernisse zu beseitigen.

10.16 TCP-Funktionen

Dieses Kapitel behandelt die vielen Funktionen von TCP. Die wichtigsten sind unten aufgeführt:

■Ports Verbindungen zuordnen

■ Initialisieren Sie Verbindungen mithilfe einer dreistufigen Bestätigung

■ Führen Sie einen langsamen Start durch, um eine Netzwerküberlastung zu vermeiden

■ Segmentierung der Daten während der Übertragung

■ Datennummerierung

■ Verarbeitung eingehender Duplikatsegmente

■ Berechnung von Prüfsummen

■ Kontrolle des Datenflusses durch das Empfangsfenster und das Sendefenster

■ Beenden der Verbindung in etablierter Weise

■ Beenden der Verbindung

■ Weiterleitung dringender Daten

■ Positive Bestätigung der Rücksendung

■ Berechnen Sie das Zeitlimit für die erneute Übertragung

■ Reduzierter Rückverkehr bei Netzwerküberlastung

■ Signalisieren, dass Segmente nicht in der richtigen Reihenfolge ankommen

■ Erkennen des Schließens des Empfangsfensters

10.17 TCP-Zustände

Eine TCP-Verbindung durchläuft mehrere Phasen: Die Verbindung wird durch den Austausch von Nachrichten hergestellt, dann werden Daten gesendet und dann wird die Verbindung durch den Austausch spezieller Nachrichten geschlossen. Jeder Schritt im Verbindungsvorgang entspricht einem bestimmten Zustand diese Verbindung. Die TCP-Software an jedem Ende der Verbindung überwacht ständig den aktuellen Status der anderen Seite der Verbindung.

Im Folgenden werfen wir einen kurzen Blick auf den typischen Zustandsübergang zwischen einem Server und einem Client, die sich an entgegengesetzten Enden einer Verbindung befinden. Unser Anspruch ist es nicht, eine erschöpfende Beschreibung aller möglichen Zustände bei der Übermittlung von Daten zu geben. Es ist in RFC 793 und dem Dokument angegeben Host-Anforderungen.

Beim Verbindungsaufbau durchlaufen Server und Client ähnliche Zustandsabfolgen. Serverstatus werden in Tabelle 10.3 angezeigt, und Clientstatus werden in Tabelle 10.4 angezeigt.


Tabelle 10.3 Serverstatussequenz

Server Status Ereignis Beschreibung
GESCHLOSSEN Dummy-Zustand vor Beginn des Verbindungsaufbaus.
Passives Öffnen durch eine Serveranwendung.
HÖREN (Tracking) Der Server wartet auf eine Verbindung vom Client.
Der TCP-Server empfängt das SYN und sendet ein SYN/ACK. Der Server hat SYN empfangen und SYN/ACK gesendet. Geht zum Warten auf ACK.
SYN-EMPFANGEN Der TCP-Server erhält eine ACK.
Etabliert (installiert) ACK empfangen, Verbindung geöffnet.

Tabelle 10.4 Client-Statussequenz

Wenn die Partner gleichzeitig versuchen würden, eine Verbindung zueinander herzustellen (was äußerst selten vorkommt), würde jeder die Zustände CLOSED, SYN-SENT, SYN-RECEIVED und ESTABLISHED durchlaufen.

Die Endparteien der Verbindung bleiben im Zustand ESTABLISHED, bis einer der Parteien startet Schließung Verbindungen durch Senden des FIN-Segments. Während eines normalen Abschlusses durchläuft die Partei, die den Abschluss initiiert, die in Tabelle 10.5 aufgeführten Zustände. Ihr Partner durchläuft die in Tabelle 10.6 dargestellten Zustände.


Tabelle 10.5 Abfolge der Zustände der Seite, die die Verbindung schließt

Abschließende Nebenzustände Ereignis Beschreibung
GEGRÜNDET Eine lokale Anwendung fordert, dass die Verbindung geschlossen wird.
TCP sendet FIN/ACK.
FIN-WAIT-1 Die Abschlussparty wartet auf die Antwort des Partners. Wir möchten Sie daran erinnern, dass möglicherweise noch neue Daten vom Partner eintreffen.
TCP erhält eine ACK.
FIN-WAIT-2 Die Abschlusspartei hat vom Peer ein ACK, aber noch kein FIN erhalten. Die schließende Partei wartet bei der Annahme eingehender Daten auf FIN.
TCP empfängt FIN/ACK.
Sendet eine Bestätigung.
ZEIT WARTET Die Verbindung wird in einem unbestimmten Zustand gehalten, um zu ermöglichen, dass doppelte Daten oder doppelte FINs, die noch im Netzwerk vorhanden sind, ankommen oder verworfen werden. Die Wartezeit beträgt das Doppelte der geschätzten maximalen Segmentlebensdauer.
GESCHLOSSEN

Tabelle 10.6 Reihenfolge der Partnerzustände beim Schließen einer Verbindung

Partnerstatus Ereignis Beschreibung
GEGRÜNDET TCP empfängt FIN/ACK.
Abwarten FIN ist angekommen.
TCP sendet ein ACK.
TCP erwartet von seiner Anwendung, dass sie die Verbindung schließt. Zu diesem Zeitpunkt sendet die Anwendung möglicherweise eine ziemlich große Datenmenge.
Die lokale Anwendung initiiert das Schließen der Verbindung.
TCP sendet FIN/ACK.
LETZTE ACK TCP wartet auf die endgültige Bestätigung.
TCP erhält eine ACK.
GESCHLOSSEN Alle Verbindungsinformationen wurden gelöscht.

10.17.1 TCP-Verbindungszustände analysieren

Team netstat -an ermöglicht es Ihnen, den aktuellen Verbindungsstatus zu überprüfen. Die Verbindungen in den Staaten werden unten angezeigt zuhören, starten, etabliert, schließen Und Zeit wartet.

Beachten Sie, dass die Nummer des Verbindungsports am Ende jeder lokalen und externen Adresse aufgeführt ist. Sie können sehen, dass sowohl für die Eingabe- als auch für die Ausgabewarteschlange TCP-Verkehr besteht.

Pro Recv-Q Send-Q Lokale Adresse Fremdadresse (Bundesstaat)
Tcp 0 0 128.121.50.145.25 128.252.223.5.1526 SYN_RCVD
Tcp 0 0 128.121.50.145.25 148.79.160.65.3368 Etabliert
Tcp 0 0 127.0.0.1.1339 127.0.0.1.111 TIME_WAIT
Tcp 0 438 128.121.50.145.23 130.132.57.246.2219 Etabliert
Tcp 0 0 128.121.50.145.25 192.5.5.1.4022 TIME_WAIT
Tcp 0 0 128.121.50.145.25 141.218.1.100.3968 TIME_WAIT
Tcp 0 848 128.121.50.145.23 192.67.236.10.1050 Etabliert
Tcp 0 0 128.121.50.145.1082 128.121.50.141.6000 Etabliert
Tcp 0 0 128.121.50.145.1022 128.121.50.141.1017 Etabliert
Tcp 0 0 128.121.50.145.514 128.121.50.141.1020 CLOSE_WAIT
Tcp 0 1152 128.121.50.145.119 192.67.239.23.3572 Etabliert
Tcp 0 0 128.121.50.145.1070 192.41.171.5.119 TIME_WAIT
Tcp 579 4096 128.121.50.145.119 204.143.19.30.1884 GEGRÜNDET
Tcp 0 0 128.121.50.145.119 192.67.243.13.3704 Etabliert
Tcp 0 53 128.121.50.145.119 192.67.236.218.2018 FIN_WAIT_1
Tcp 0 0 128.121.50.145.119 192.67.239.14.1545 Etabliert

10.18 Hinweise zu Implementierungen

Das TCP-Protokoll war von Anfang an darauf ausgelegt, Netzwerkgeräte verschiedener Hersteller miteinander zu verbinden. Die TCP-Spezifikation legt nicht genau fest, wie die internen Implementierungsstrukturen funktionieren sollen. Diese Fragen werden den Entwicklern überlassen, die die Aufgabe haben, die besten Mechanismen für jede spezifische Implementierung zu finden.

Sogar RFC 1122 (Dokument Host-Anforderungen – Anforderungen an Hosts) lässt ausreichend Spielraum für Variationen. Jede der implementierten Funktionen ist mit einem bestimmten Kompatibilitätsgrad gekennzeichnet:

■ MAI (Zulässig)

■ DARF NICHT

Leider gibt es manchmal Produkte, die MUSS-Anforderungen nicht umsetzen. Dies führt dazu, dass Benutzer mit der Unannehmlichkeit einer verringerten Leistung konfrontiert werden.

Einige gute Implementierungspraktiken werden in den Standards nicht abgedeckt. Eine verbesserte Sicherheit kann beispielsweise dadurch erreicht werden, dass die Verwendung bekannter Ports durch privilegierte Prozesse auf dem System eingeschränkt wird, sofern es sich um lokale Ports handelt Betriebssystem Diese Methode wird unterstützt. Um die Leistung zu verbessern, sollten Implementierungen gesendete oder abgerufene Daten so wenig wie möglich kopieren und verschieben.

Standard-Anunbestimmt(sowie Sicherheitsrichtlinien), so dass Freiraum zum Experimentieren mit verschiedenen Sätzen von Softwaretools vorhanden ist. Dies kann jedoch dazu führen, dass auf jeder Plattform unterschiedliche Programmierschnittstellen verwendet werden und es nicht möglich ist, Anwendungssoftware zwischen Plattformen zu verschieben.

Tatsächlich basieren Entwickler ihre Toolkits auf der von Berkeley entlehnten Socket-Programmierschnittstelle. Die Bedeutung der Softwareschnittstelle nahm mit der Einführung von WINSock (Windows Socket) zu, was zu einer Verbreitung neuer Desktop-Anwendungen führte, die auf jeder mit dem TCP/IP-Stack kompatiblen WINSock-Schnittstelle ausgeführt werden konnten.

10.19 Weiterführende Literatur

Der ursprüngliche TCP-Standard ist in RFC 793 definiert. Upgrades, Revisionen und Kompatibilitätsanforderungen werden in RFC 1122 behandelt. Kern und Partridge haben den Artikel veröffentlicht Verbesserung der Round-Trip-Schätzungen in zuverlässigen Transportprotokollen Im Magazin Verfahren des ACM SIGCOMM 1987. Jacobsons Artikel Stauvermeidung und -kontrolle erschien in Vorträge des ACM SIGCOMM 1988 Workshops. Jacobson hat außerdem mehrere RFCs zur Überarbeitung von Leistungsalgorithmen herausgegeben.

Server, die diese Protokolle implementieren Firmennetzwerk, stellen Sie dem Client eine IP-Adresse, ein Gateway, eine Netzmaske, Nameserver und sogar einen Drucker zur Verfügung. Benutzer müssen ihre Hosts nicht manuell konfigurieren, um das Netzwerk nutzen zu können.

Das Betriebssystem QNX Neutrino implementiert ein weiteres Autokonfigurationsprotokoll namens AutoIP, bei dem es sich um ein Projekt des IETF-Komitees handelt. automatische Konfiguration. Dieses Protokoll wird in kleinen Netzwerken verwendet, um Hosts verbindungslokale IP-Adressen zuzuweisen. Das AutoIP-Protokoll ermittelt unabhängig die lokale IP-Adresse der Verbindung, indem es ein Aushandlungsschema mit anderen Hosts verwendet und keinen zentralen Server kontaktiert.

Verwendung des PPPoE-Protokolls

Die Abkürzung PPPoE steht für Point-to-Point Protocol over Ethernet. Dieses Protokoll kapselt Daten für die Übertragung über ein Ethernet-Netzwerk mit einer Bridged-Topologie.

PPPoE ist eine Spezifikation für die Verbindung von Ethernet-Benutzern mit dem Internet über eine Breitbandverbindung, beispielsweise eine gemietete digitale Teilnehmerleitung, ein drahtloses Gerät oder ein Kabelmodem. Durch die Verwendung des PPPoE-Protokolls und eines Breitbandmodems können Benutzer lokal kommunizieren Computernetzwerk individueller authentifizierter Zugang zu Hochgeschwindigkeits-Datennetzen.

Das PPPoE-Protokoll kombiniert Ethernet-Technologie mit dem PPP-Protokoll und stellt so effektiv für jeden Benutzer eine separate Verbindung zu einem Remote-Server her. Zugriffskontrolle, Verbindungsabrechnung und Auswahl des Dienstanbieters werden für Benutzer und nicht für Hosts bestimmt. Der Vorteil dieses Ansatzes besteht darin, dass weder die Telefongesellschaft noch der Internetanbieter hierfür besondere Unterstützung leisten müssen.

Im Gegensatz zu DFÜ-Verbindungen sind DSL- und Kabelmodemverbindungen immer aktiv. Da die physische Verbindung zu einem Remote-Dienstanbieter von mehreren Benutzern gemeinsam genutzt wird, ist eine Abrechnungsmethode erforderlich, die die Absender und Ziele des Datenverkehrs aufzeichnet und den Benutzern Gebühren berechnet. Das PPPoE-Protokoll ermöglicht es dem Benutzer und dem Remote-Host, die an einer Kommunikationssitzung teilnehmen, während eines ersten Austauschanrufs die Netzwerkadressen des jeweils anderen zu erfahren Erkennung(Entdeckung). Sobald eine Sitzung zwischen einem einzelnen Benutzer und einem Remote-Host (z. B. einem Internetdienstanbieter) eingerichtet wurde, kann die Sitzung zu Abrechnungszwecken überwacht werden. Viele Haushalte, Hotels und Unternehmen bieten öffentlichen Internetzugang über digitale Teilnehmeranschlüsse mithilfe der Ethernet-Technologie und des PPPoE-Protokolls.

Eine Verbindung über das PPPoE-Protokoll besteht aus einem Client und einem Server. Der Client und der Server arbeiten über jede Schnittstelle, die den Ethernet-Spezifikationen nahekommt. Diese Schnittstelle wird verwendet, um IP-Adressen an Clients zu vergeben und diese IP-Adressen mit Benutzern und optional mit Arbeitsstationen zu verknüpfen, und nicht nur mit der arbeitsstationsbasierten Authentifizierung. Der PPPoE-Server erstellt für jeden Client eine Punkt-zu-Punkt-Verbindung.

Einrichten einer PPPoE-Sitzung

Um eine PPPoE-Sitzung zu erstellen, sollten Sie den Dienst nutzenpppoed. Modulio-pkt-*nBietet PPPoE-Protokolldienste. Zuerst müssen Sie laufenio-pkt-*Mitgeeigneter Fahrer. Beispiel:

Reisen durch Netzwerkprotokolle.

TCP und UDP sind beide Protokolle der Transportschicht. UDP ist ein verbindungsloses Protokoll mit nicht garantierter Paketzustellung. TCP (Transmission Control Protocol) ist ein verbindungsorientiertes Protokoll mit garantierter Paketzustellung. Zunächst erfolgt ein Handschlag (Hallo. | Hallo. | Lass uns chatten? | Lass uns gehen.), danach gilt die Verbindung als hergestellt. Anschließend werden Pakete über diese Verbindung hin- und hergesendet (es läuft ein Gespräch) und es wird geprüft, ob das Paket den Empfänger erreicht hat. Wenn das Paket verloren geht oder mit fehlerhafter Prüfsumme angekommen ist, wird es erneut gesendet („Wiederholen, ich habe es nicht gehört“). Somit ist TCP zwar zuverlässiger, aber aus Implementierungssicht komplexer und benötigt dementsprechend mehr Taktzyklen/Speicher, was für Mikrocontroller nicht zuletzt wichtig ist. Beispiele für Anwendungsprotokolle, die TCP verwenden, sind FTP, HTTP, SMTP und viele andere.

TL;DR

HTTP (Hypertext Transfer Protocol) ist ein Anwendungsprotokoll, mit dem der Server Seiten an unseren Browser sendet. HTTP ist mittlerweile weit verbreitet in Weltweites Netz um Informationen von Websites zu erhalten. Das Bild zeigt eine Lampe an einem Mikrocontroller mit integriertem Betriebssystem, bei dem die Farben über einen Browser eingestellt werden.

Das HTTP-Protokoll ist textbasiert und recht einfach. Tatsächlich sieht die gesendete GET-Methode so aus: Netcat-Dienstprogramm zur lokalen IPv6-Serveradresse mit Lichtern:

~$ nc fe80::200:e2ff:fe58:b66b%mazko 80<

Bei der HTTP-Methode handelt es sich normalerweise um ein kurzes englisches Wort, das in Großbuchstaben geschrieben wird und bei dem die Groß-/Kleinschreibung beachtet wird. Jeder Server muss mindestens die Methoden GET und HEAD unterstützen. Neben den Methoden GET und HEAD werden häufig auch die Methoden POST, PUT und DELETE verwendet. Die GET-Methode wird verwendet, um den Inhalt einer angegebenen Ressource anzufordern, in unserem Fall hier GET /b HTTP/1.0, wobei der /b-Pfad für die Farbe (blau) verantwortlich ist. Serverantwort:

HTTP/1.0 200 OK Server: Contiki/2.4 http://www.sics.se/contiki/ Verbindung: schließen Cache-Steuerung: kein Cache, kein Speichern, muss erneut validiert werden Pragma: kein Cache Läuft ab: 0 Inhalt- Typ: Text/HTML Contiki RGB

Rot ist AUS

Grün ist AUS

Blau ist AN

Der Statuscode (wir haben 200) ist Teil der ersten Zeile der Serverantwort. Es ist eine dreistellige Ganzzahl. Die erste Ziffer gibt die Klasse der Bedingung an. Auf den Antwortcode folgt normalerweise ein erklärender Satz in englischer Sprache, getrennt durch ein Leerzeichen, der der Person den Grund für diese bestimmte Antwort erklärt. In unserem Fall funktionierte der Server fehlerfrei, alles war in Ordnung (OK).

Sowohl die Anfrage als auch die Antwort enthalten Header (jede Zeile ist ein separates Header-Feld, das Name-Wert-Paar wird durch einen Doppelpunkt getrennt). Die Header enden mit einer Leerzeile, danach können Daten folgen.

Mein Browser weigert sich, die lokale IPv6-Adresse zu öffnen, daher wird eine zusätzliche Adresse in die Mikrocontroller-Firmware geschrieben und das gleiche Präfix muss auch der virtuellen Netzwerkschnittstelle des Simulators zugewiesen werden:

~$ sudo ip addr add abcd::1/64 dev mazko # linux ~$ netsh interface ipv6 set address mazko abcd::1 # windows ~$ curl http://



Client-Server-Anwendung auf einem TCP-Stream-Socket

Das folgende Beispiel verwendet TCP, um geordnete, zuverlässige bidirektionale Byteströme bereitzustellen. Lassen Sie uns eine vollständige Anwendung erstellen, die einen Client und einen Server umfasst. Zuerst zeigen wir, wie man einen Server mit TCP-Stream-Sockets erstellt, und dann eine Client-Anwendung zum Testen unseres Servers.

Das folgende Programm erstellt einen Server, der Verbindungsanfragen von Clients empfängt. Der Server wird synchron aufgebaut, daher wird die Thread-Ausführung blockiert, bis der Server einer Verbindung mit dem Client zustimmt. Diese Anwendung demonstriert einen einfachen Server, der auf einen Client reagiert. Der Client beendet die Verbindung, indem er eine Nachricht an den Server sendet .

TCP-Server

Der Aufbau der Serverstruktur ist im folgenden Funktionsdiagramm dargestellt:

Hier ist der vollständige Code für das Programm SocketServer.cs:

// SocketServer.cs using System; Verwenden von System.Text; mit System.Net; Verwenden von System.Net.Sockets; namespace SocketServer ( class Program ( static void Main(string args) ( // Setze den lokalen Endpunkt für den Socket IPHostEntry ipHost = Dns.GetHostEntry("localhost"); IPAddress ipAddr = ipHost.AddressList; IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000 ); // Einen Tcp/IP-Socket erstellen Socket sListener = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // Den Socket dem lokalen Endpunkt zuweisen und auf eingehende Sockets warten try ( sListener.Bind( ipEndPoint); sListener. Listen(10); // Auf Verbindungen warten while (true) ( ​​​​Console.WriteLine("Warten auf eine Verbindung an Port (0)", ipEndPoint); // Das Programm hält an und wartet auf eine eingehende Verbindung Socket handler = sListener.Accept(); string data = null; // Wir haben darauf gewartet, dass der Client versucht, eine Verbindung zu uns herzustellen byte bytes = new byte; int bytesRec = handler.Receive(bytes); data += Encoding. UTF8.GetString(bytes, 0, bytesRec); // Daten auf der Konsole anzeigen Console.Write("Received text: " + data + "\n\n"); // Eine Antwort an den Client senden\ string reply = „Vielen Dank für die Anfrage in „ + data.Length.ToString() + „ Zeichen“; byte msg = Encoding.UTF8.GetBytes(reply); handler.Send(msg); if (data.IndexOf(" ") > -1) ( Console.WriteLine("Der Server hat die Verbindung zum Client beendet."); break; ) handler.Shutdown(SocketShutdown.Both); handler.Close(); ) ) Catch (Exception ex) ( Console.WriteLine (ex.ToString()); ) schließlich ( Console.ReadLine(); ) ) ) )

Schauen wir uns die Struktur dieses Programms an.

Der erste Schritt besteht darin, den Socket auf einen lokalen Endpunkt festzulegen. Bevor Sie einen Socket öffnen, um auf Verbindungen zu warten, müssen Sie eine lokale Endpunktadresse dafür vorbereiten. Eine eindeutige TCP/IP-Dienstadresse wird durch die Kombination der IP-Adresse des Hosts mit der Dienstportnummer bestimmt, wodurch der Dienstendpunkt erstellt wird.

Die Dns-Klasse stellt Methoden bereit, die Informationen zu den Netzwerkadressen zurückgeben, die von einem Gerät im lokalen Netzwerk unterstützt werden. Wenn ein LAN-Gerät mehr als eine Netzwerkadresse hat, gibt die DNS-Klasse Informationen über alle Netzwerkadressen zurück und die Anwendung muss die entsprechende Adresse aus dem Array auswählen, die bereitgestellt werden soll.

Erstellen wir einen IPEndPoint für den Server, indem wir die erste IP-Adresse des Host-Computers, die von der Dns.Resolve()-Methode erhalten wurde, mit der Portnummer kombinieren:

IPHostEntry ipHost = Dns.GetHostEntry("localhost"); IPAddress ipAddr = ipHost.AddressList; IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);

Hier stellt die IPEndPoint-Klasse localhost auf Port 11000 dar. Als Nächstes erstellen wir einen Stream-Socket mit einer neuen Instanz der Socket-Klasse. Nachdem wir einen lokalen Endpunkt eingerichtet haben, der auf Verbindungen wartet, können wir einen Socket erstellen:

Socket sListener = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

Überweisen AdresseFamilie Gibt die Adressierungsschemata an, die eine Instanz der Socket-Klasse zum Auflösen einer Adresse verwenden kann.

Im Parameter Steckdosentyp TCP- und UDP-Sockets sind unterschiedlich. Darin können Sie unter anderem folgende Werte definieren:

Dgram

Unterstützt Datagramme. Für den Dgram-Wert muss Udp für den Protokolltyp und InterNetwork im Adressfamilienparameter angegeben werden.

Roh

Unterstützt den Zugriff auf das zugrunde liegende Transportprotokoll.

Strom

Unterstützt Stream-Sockets. Für den Stream-Wert muss Tcp als Protokolltyp angegeben werden.

Der dritte und letzte Parameter gibt den für den Socket erforderlichen Protokolltyp an. Im Parameter Protokolltyp Sie können die folgenden wichtigsten Werte angeben: Tcp, Udp, Ip, Raw.

Der nächste Schritt sollte darin bestehen, den Socket mithilfe der Methode zuzuweisen Binden(). Wenn ein Socket von einem Konstruktor geöffnet wird, wird ihm kein Name zugewiesen, sondern nur ein Handle reserviert. Um dem Server-Socket einen Namen zuzuweisen, wird die Methode Bind() aufgerufen. Damit ein Client-Socket einen TCP-Stream-Socket identifizieren kann, muss das Serverprogramm seinem Socket einen Namen geben:

SListener.Bind(ipEndPoint);

Die Bind()-Methode bindet einen Socket an einen lokalen Endpunkt. Die Bind()-Methode muss vor allen Aufrufversuchen der Listen()- und Accept()-Methoden aufgerufen werden.

Nachdem Sie nun einen Socket erstellt und ihm einen Namen zugeordnet haben, können Sie mit der Methode eingehende Nachrichten abhören Hören(). Im Überwachungszustand wartet der Socket auf eingehende Verbindungsversuche:

SListener.Listen(10);

Der Parameter definiert Rückstand, was die maximale Anzahl der in der Warteschlange wartenden Verbindungen angibt. Im obigen Code ermöglicht der Parameterwert die Ansammlung von bis zu zehn Verbindungen in der Warteschlange.

Im Listening-Zustand müssen Sie bereit sein, einer Verbindung mit dem Client zuzustimmen, für den die Methode verwendet wird Akzeptieren(). Diese Methode stellt eine Client-Verbindung her und schließt die Client- und Servernamenszuordnung ab. Die Accept()-Methode blockiert den Thread des aufrufenden Programms, bis eine Verbindung eintrifft.

Die Accept()-Methode entfernt die erste Verbindungsanforderung aus der Warteschlange der ausstehenden Anforderungen und erstellt einen neuen Socket, um sie zu verarbeiten. Obwohl ein neuer Socket erstellt wird, lauscht der ursprüngliche Socket weiterhin und kann mit Multithreading verwendet werden, um mehrere Verbindungsanforderungen von Clients anzunehmen. Keine Serveranwendung sollte einen Listening-Socket schließen. Es muss weiterhin mit den von der Accept-Methode erstellten Sockets zusammenarbeiten, um eingehende Clientanforderungen zu verarbeiten.

While (true) ( ​​​​Console.WriteLine("Warten auf eine Verbindung an Port (0)", ipEndPoint); // Das Programm hält an, während es auf eine eingehende Verbindung wartet Socket handler = sListener.Accept();

Sobald Client und Server eine Verbindung zueinander aufgebaut haben, können über die Methoden Nachrichten gesendet und empfangen werden Schicken() Und Erhalten() Klasse Socket.

Die Methode Send() schreibt ausgehende Daten in den verbundenen Socket. Die Methode „Receive()“ liest eingehende Daten in den Stream-Socket. Bei Verwendung eines TCP-basierten Systems muss vor der Ausführung der Methoden Send() und Receive() eine Verbindung zwischen den Sockets hergestellt werden. Das genaue Protokoll zwischen den beiden kommunizierenden Einheiten muss im Voraus definiert werden, damit sich die Client- und Serveranwendungen nicht gegenseitig blockieren, indem sie nicht wissen, wer ihre Daten zuerst senden soll.

Wenn der Datenaustausch zwischen Server und Client abgeschlossen ist, müssen Sie die Verbindung mithilfe der Methoden schließen Abschalten() Und Schließen():

Handler.Shutdown(SocketShutdown.Both); handler.Close();

SocketShutdown ist eine Aufzählung, die drei zu stoppende Werte enthält: Beide- stoppt das Senden und Empfangen von Daten über den Socket, Erhalten- Verhindert, dass der Socket Daten empfängt und Schicken- Hört auf, Daten über den Socket zu senden.

Der Socket wird durch Aufrufen der Close()-Methode geschlossen, die auch die Connected-Eigenschaft des Sockets auf false setzt.

TCP-Client

Die Funktionen, die zum Erstellen einer Clientanwendung verwendet werden, ähneln mehr oder weniger denen einer Serveranwendung. Wie beim Server werden dieselben Methoden verwendet, um den Endpunkt zu ermitteln, den Socket zu instanziieren, Daten zu senden und zu empfangen und den Socket zu schließen.