Wann sollte ich TCP_NODELAY verwenden und wann TCP_CORK?

72

Ich habe verstanden, dass beide Nagles Algorithmus deaktivieren.

Wann sollte / sollte ich nicht jeden von ihnen verwenden?

Whymarrh
quelle

Antworten:

90

Erstens deaktivieren nicht beide den Nagle-Algorithmus.

Der Nagle-Algorithmus dient dazu, mehr kleine Netzwerkpakete im Kabel zu reduzieren. Der Algorithmus lautet: Wenn die Daten kleiner als ein Grenzwert sind (normalerweise MSS), warten Sie, bis ACK für zuvor gesendete Pakete empfangen wurde, und sammeln Sie in der Zwischenzeit Daten vom Benutzer. Senden Sie dann die gesammelten Daten.

if [ data > MSS ]
    send(data)
else
    wait until ACK for previously sent data and accumulate data in send buffer (data)
    And after receiving the ACK send(data)

Dies hilft in Anwendungen wie Telnet. Das Warten auf die ACK kann jedoch die Latenz beim Senden von Streaming-Daten erhöhen. Wenn der Empfänger die "verzögerte ACK-Richtlinie" implementiert, führt dies zu einer vorübergehenden Deadlock-Situation. In solchen Fällen ist das Deaktivieren des Nagle-Algorithmus eine bessere Option.

Daher wird TCP_NODELAY zum Deaktivieren des Nagle-Algorithmus verwendet.

TCP_CORK sammelt aggressiv Daten. Wenn TCP_CORK in einem Socket aktiviert ist, werden keine Daten gesendet, bis der Puffer bis zu einem festen Grenzwert gefüllt ist. Ähnlich wie beim Nagle-Algorithmus werden auch Daten vom Benutzer akkumuliert, jedoch bis der Puffer bis zum Empfang von ACK bis zu einem festen Grenzwert gefüllt ist. Dies ist nützlich, wenn Sie mehrere Datenblöcke senden. Bei der Verwendung von TCP_CORK müssen Sie jedoch vorsichtiger sein.

Bis zum 2.6-Kernel schließen sich beide Optionen gegenseitig aus. Aber im späteren Kernel können beide zusammen existieren. In diesem Fall wird TCP_CORK stärker bevorzugt.

Ref:

Das B
quelle
6
Beachten Sie die Antwort von Hussein Galal, in der klargestellt wird, dass TCP_CORK vor dem Senden von Daten nur maximal 200 ms verzögert.
b4hand
1
"Dies wird in Anwendungen wie Telnet helfen."? Vielmehr ist das Gegenteil der Fall. Wenn Sie eine Taste drücken, wird das Senden Ihres Tastendrucks auf die andere Seite verzögert, bis eine Bestätigung für den letzten Tastendruck empfangen wurde. Dies führt zu einer hohen Verzögerung zwischen Tastendruck und gesendetem Schlüssel, und ich würde keine Situation kennen, in der dies wünschenswert ist.
Mecki
27

TCP_NODELAY

Wird verwendet, um den Nagle-Algorithmus zu deaktivieren, um TCP / IP-Netzwerke zu verbessern und die Anzahl der Pakete zu verringern, indem gewartet wird, bis eine Bestätigung der zuvor gesendeten Daten empfangen wird, um die akkumulierten Pakete zu senden.

// Aus dem tcp (7) Handbuch:

TCP_CORK(oder TCP_NOPUSHin FreeBSD)

Wenn festgelegt, senden Sie keine Teilframes aus. Alle Teilframes in der Warteschlange werden gesendet, wenn die Option erneut deaktiviert wird. Dies ist nützlich, um Headern vor dem Aufruf voranzustellen sendfile(2)oder um den Durchsatz zu optimieren. Wie derzeit implementiert, gibt es eine ** Obergrenze von 200 Millisekunden ** für die Zeit, für die die Ausgabe verkorkt wird TCP_CORK. Wenn diese Obergrenze erreicht ist, werden Daten in der Warteschlange automatisch übertragen . Diese Option kann TCP_NODELAYnur seit Linux 2.5.71 kombiniert werden . Diese Option sollte nicht in Code verwendet werden, der portabel sein soll.

Hussein Galal
quelle
6
Vielen Dank, dass Sie darauf hingewiesen haben, was viele Anleitungen völlig falsch gemacht haben, dass TCP_CORK nur um 200 ms (max.) Verzögert. Es ist buchstäblich kein CORK, der sich bis zum Entfernen verklemmen kann.
Orwellophile
10

Es ist eine Optimierung, also wie jede Optimierung:

  1. Benutze es nicht
  2. Warten Sie, bis die Leistung zu einem Problem wird, und stellen Sie dann fest, dass die Socket-Latenz definitiv die Ursache dafür ist. Tests haben gezeigt, dass dies das Problem definitiv beheben wird. Dies ist der einfachste Weg, dies zu beheben.

Grundsätzlich besteht das Ziel darin, zu vermeiden, dass mit sendfile () und seinen Freunden mehrere Frames gesendet werden müssen, in denen ein einzelner Frame verwendet werden kann.

So senden Sie beispielsweise auf einem Webserver die Header gefolgt vom Dateiinhalt, die Header werden im Speicher zusammengestellt und die Datei wird dann direkt vom Kernel gesendet. Mit TCP_CORK können Sie die Header und den Anfang der Datei in einem einzigen Frame senden, auch mit TCP_NODELAY, da sonst der erste Block sofort gesendet wird.

MarkR
quelle
48
Nagle selbst ist eine Optimierung, also sollten Sie es nach Ihrer Logik ausschalten und nur bei Bedarf
einschalten
3
Nagle ist standardmäßig aktiviert und Sie müssen keinen Code schreiben, um es zu aktivieren. Es wird also trotzdem passieren. Und nein, wenn Sie Ihren eigenen TCP-Stack schreiben würden, wenn Sie Nagle nicht implementieren müssten, würden Sie dies nicht tun.
MarkR
7
Es würde mich nicht wundern, wenn das in ein paar Jahren tatsächlich passieren würde (jemand, der es nicht mehr implementiert). Das Hauptanliegen vor 30 oder 40 Jahren war, dass Leute, die mit ungefähr 2 Zeichen pro Sekunde auf Telnet tippen, ein Paket für jedes Zeichen generieren würden. Dies ist heutzutage kaum ein Problem, da die Bandbreite viel höher ist, die Remote-Anmeldung in Bezug auf den Datenverkehr keine große Rolle spielt und Blockchiffren ohnehin auf so ziemlich jeden Remote-Anmeldeverkehr angewendet werden. Mit einer 128-Bit-Blockverschlüsselung können Sie auf keinen Fall weniger als 16 Byte senden (jedenfalls nicht, wenn Sie sie am anderen Ende dekodieren möchten).
Damon
1
@camh Ich weiß, dass Sie Spaß gemacht haben, aber zur Verteidigung von OP ist das Deaktivieren von Nagle manchmal eine Optimierung der Latenzvariablen .
Mateen Ulhaq
-1

TCP_CORK ist das Gegenteil von TCP_NODELAY. Ersteres erzwingt eine Verzögerung der Paketakkumulation; Letzteres deaktiviert es.

fche
quelle
17
TCP_CORKist nicht das Gegenteil von TCP_NODELAY. Der Nagle-Algorithmus aggregiert Daten, während er auf eine Rückgabe-ACK wartet, die durch die letztere Option deaktiviert wird. Ersteres aggregiert Daten stattdessen basierend auf dem Pufferdruck.
Joshperry