Die Prozesspakete mit dem SYN-Flag im RFC793-Dokument können keine Daten übertragen, d. h. die ersten beiden Pakete des Drei-Wege-Handshakes können keine Daten übertragen (logisch gesehen wurde die Verbindung noch nicht hergestellt, daher erscheint es etwas unvernünftig, Daten zu übertragen). Der entscheidende Punkt ist, ob der dritte Handshake Daten übertragen kann. Lassen Sie mich zunächst das Fazit ziehen: Der dritte Handshake im Drei-Wege-Handshake-Prozess des TCP-Protokolls zum Herstellen einer Verbindung ermöglicht die Datenübertragung. Beziehen wir uns nun auf den Teil zum Verbindungsaufbau im obigen TCP-Zustandsänderungsdiagramm und schauen wir uns an, was im RFC793-Dokument steht. Im Dokument RFC793 heißt es (unter Auslassung unwichtiger Teile) Folgendes: Der entscheidende Punkt ist dieser Satz „Daten oder Steuerelemente, die zur Übertragung in die Warteschlange gestellt wurden, können enthalten sein“, was bedeutet, dass der Standard angibt, dass das ACK-Paket des dritten Handshakes Daten enthalten kann. Zunächst wird das Paket des dritten Handshakes vom Verbindungsinitiator (im Folgenden als Client bezeichnet) an den Port-Listener (im Folgenden als Server bezeichnet) gesendet. Daher müssen Sie nach dem Empfang des Pakets nur den Verarbeitungsprozess des Kernel-Protokollstapels finden, wenn sich eine Verbindung im Status SYN-RECV (SYN_RECEIVED in der Abbildung) befindet. Nach einiger Suche fand ich heraus, dass die Funktion tcp_rcv_state_process in der Datei tcp_input.c im Verzeichnis net\ipv4 diesen Prozess handhabt. Wie in der Abbildung gezeigt: Bei dieser Funktion handelt es sich eigentlich um eine TCP-Zustandsmaschine, die zur Verarbeitung empfangener Datenpakete dient, wenn sich die TCP-Verbindung in verschiedenen Zuständen befindet. Hier gibt es mehrere parallele Switch-Anweisungen. Da die Funktion sehr lang ist, kann es leicht zu Fehlinterpretationen der hierarchischen Beziehung kommen. Die folgende Abbildung zeigt die Verarbeitung des SYN-RECV-Zustands nach der Vereinfachung des Codes, der nicht berücksichtigt werden muss: Es ist wichtig zu beachten, dass die beiden Switch-Anweisungen parallel sind. Wenn der TCP_SYN_RECV-Status ein gültiges und standardisiertes Zweiwege-Handshake-Paket empfängt, wird der Socket-Status daher sofort auf den TCP_ESTABLISHED-Status gesetzt. Wenn die Ausführung den folgenden TCP_ESTABLISHED-Statusfall erreicht, wird sie mit der Verarbeitung der darin enthaltenen Daten (sofern vorhanden) fortfahren. Das Obige zeigt, dass der Server die Daten normal verarbeiten kann, wenn die ACK des vom Client gesendeten dritten Handshakes Daten enthält. Und was ist mit der Client-Seite? Sehen wir uns an, wie der Client das dritte ACK-Paket sendet, wenn er sich im Status SYN-SEND befindet. Wie in der Abbildung gezeigt: Die Implementierung der Funktion tcp_rcv_synsent_state_process ist relativ lang, daher hier die letzten wichtigen Punkte: Es ist auf den ersten Blick klar, oder? Wenn die Bedingung nicht erfüllt ist, antworten Sie direkt mit einem separaten ACK-Paket. Wenn eine Bedingung erfüllt ist, verwenden Sie die Funktion inet_csk_reset_xmit_timer, um einen Timer für eine kurze Wartezeit einzustellen. Wenn während dieses Zeitraums Daten vorhanden sind, wird ACK zusammen mit den Daten gesendet, es sind jedoch keine Daten vorhanden, um mit ACK zu antworten. Die bisherigen Zweifel sind ausgeräumt. Bedingung 1: sk->sk_write_pending != 0 Der Standardwert dieses Wertes ist 0. Was kann also dazu führen, dass er ungleich 0 ist? Die Antwort lautet: Wenn die Funktion des Protokollstapels zum Senden von Daten auf einen Socket-Status stößt, der nicht ESTABLISHED ist, führt sie eine ++-Operation für diese Variable aus und wartet einen kurzen Moment, bevor sie versucht, Daten zu senden. Siehe Bild: Die Funktion sk_stream_wait_connect in net/core/stream.c macht Folgendes: sk->sk_write_pending wird erhöht und Daten werden gesendet, nachdem die Socket-Verbindung den Status ESTABLISHED erreicht hat. Das erklärt es deutlich. Der Standardarbeitsmodus des Linux-Sockets ist das Blockieren, d. h. der Verbindungsaufruf des Clients wird standardmäßig blockiert und kehrt erst zurück, wenn der Drei-Wege-Handshake-Prozess abgeschlossen ist oder ein Fehler auftritt. Dann wartet nc, ein Befehlszeilen-Applet, das vollständig mit blockierenden Sockets implementiert ist und die Standard-Socket-Parameter nicht ändert, auf die erfolgreiche oder fehlgeschlagene Verbindungsmeldung, bevor es Daten sendet. Aus diesem Grund können wir die Daten im Paket des dritten Handshakes nicht erfassen. Richten Sie dann einen nicht blockierenden Socket ein und senden Sie die Daten sofort nach der Verbindung. Wenn der Verbindungsvorgang nicht sofort erfolgreich ist, haben Sie möglicherweise die Möglichkeit, das dritte Handshake-Paket mit Daten anzuzeigen. Auch wenn es sich bei der Open-Source-Netzwerkbibliothek um einen nicht blockierenden Socket handelt, überwacht sie dennoch die Schreibereignisse des Sockets und schreibt Daten erst, nachdem bestätigt wurde, dass die Verbindung erfolgreich ist. Die Einsparung dieses vernachlässigbaren Leistungsgewinns ist wirklich nicht so wertvoll wie die Verwendung von sicherem und zuverlässigem Code. Bedingung 2: icsk->icsk_accept_queue.rskq_defer_accept != 0 Dieser Zustand ist sehr merkwürdig. defer_accept ist eine Socket-Option, die zum Verzögern der Annahme verwendet wird. Tatsächlich wird die Verbindung erst hergestellt, nachdem die ersten Daten empfangen wurden. Die Option tcp_defer_accept wird im Allgemeinen serverseitig verwendet und wirkt sich auf die SYN- und ACCEPT-Warteschlangen des Sockets aus. Wenn es nicht standardmäßig festgelegt ist, tritt der Socket nach Abschluss des Drei-Wege-Handshakes in die Akzeptanzwarteschlange ein und die Anwendungsschicht erkennt und AKZEPTIERT die zugehörige Verbindung. Wenn tcp_defer_accept gesetzt ist, wird der Drei-Wege-Handshake abgeschlossen und der Socket gelangt nicht in die ACCEPT-Warteschlange, sondern bleibt direkt in der SYN-Warteschlange (es gibt eine Längenbeschränkung, und der Kernel lehnt neue Verbindungen ab, wenn die Länge diese überschreitet), bis die Daten tatsächlich gesendet und dann in die ACCEPT-Warteschlange gestellt werden. Der Server der diesen Parameter setzt kann nach dem Akzeptieren direkt lesen, das heißt es müssen Daten vorhanden sein und es spart außerdem einen Systemaufruf. Die SYN-Warteschlange speichert Sockets im Status SYN_RECV. Die Länge wird durch den Parameter net.ipv4.tcp_max_syn_backlog gesteuert. Die Akzeptanzwarteschlange wird durch den Parameter backlog festgelegt, wenn das Abhören aufgerufen wird. Das harte Kernellimit wird durch net.core.somaxconn begrenzt, d. h. der tatsächliche Wert wird durch min(backlog,somaxconn) bestimmt. Interessant ist, dass, wenn der Client zuerst an einen Port und eine IP bindet, dann setsockopt(TCP_DEFER_ACCEPT) und dann eine Verbindung zum Server herstellt, rskq_defer_accept=1 erscheint. Zu diesem Zeitpunkt stellt der Kernel einen Timer ein, um auf die Daten zu warten, bevor er auf das ACK-Paket antwortet. Ich persönlich habe das noch nie gemacht. Geht es nur darum, das Senden leerer ACK-Pakete zu reduzieren, um die Leistung zu verbessern? Wenn ein Klassenkamerad es weiß, lassen Sie es mich bitte wissen, danke. Bedingung 3: icsk->icsk_ack.pingpong != 0 Das Pingpong-Attribut ist eigentlich eine Socket-Option, die angibt, ob der aktuelle Link ein interaktiver Datenstrom ist. Wenn sein Wert 1 ist, bedeutet dies, dass es sich um einen interaktiven Datenstrom handelt und ein verzögerter Bestätigungsmechanismus verwendet wird. Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, er wird für jedermanns Studium hilfreich sein. Ich hoffe auch, dass jeder 123WORDPRESS.COM unterstützen wird. Das könnte Sie auch interessieren:
|
<<: Vue3 (V) Details zur Integration der HTTP-Bibliothek axios
>>: Tutorial zur HTML-Tabellenauszeichnung (28): Farbattribut für Zellrahmen BORDERCOLOR
Frage Wie greife ich in Docker auf die lokale Dat...
<br />Einige Webseiten sehen nicht groß aus,...
Wenn wir den Tabellennamen ändern oder die Tabell...
Es gab bereits einen Artikel über den Ausführungs...
Wenn Sie Ihren Hostnamen ändern möchten, können S...
Einführung in den Lastenausgleich Bevor wir die L...
TabIndex dient zum Drücken der Tabulatortaste, um ...
Wie erstelle ich mit HTML, CSS und JS einen einfa...
Inhaltsverzeichnis Vorwort Die Rolle des Schlüsse...
Inhaltsverzeichnis Vorwort 1. Ursache des Problem...
Beim Erstellen eines Formulars in einem aktuellen...
Der Autor stieß kürzlich bei seiner Arbeit auf ei...
Der Befehl tee wird hauptsächlich verwendet, um d...
JSON ist ein leichtes Datenaustauschformat, das e...
Vorwort Nginx ist ein auf Leistung ausgelegter HT...