it-swarm.com.de

Tut ein TCP Steckdosenanschluss haben ein "Keep Alive"?

Ich habe von HTTP keep-alive gehört, aber jetzt möchte ich eine Socket-Verbindung mit einem Remote-Server herstellen.
Wird diese Socket-Verbindung nun für immer offen bleiben oder ist ein Timeout-Limit damit verbunden, das dem HTTP-Keep-Alive ähnelt?

71
Kevin Boyd

TCP-Sockets bleiben geöffnet, bis sie geschlossen werden.

Das heißt, es ist sehr schwierig, eine unterbrochene Verbindung zu erkennen (unterbrochen, da ein Router gestorben ist usw., im Gegensatz zu einer geschlossenen), ohne tatsächlich Daten zu senden. Daher führen die meisten Anwendungen gelegentlich eine Art Ping/Pong-Reaktion aus, nur um sicherzustellen, dass dies geschieht Die Verbindung ist tatsächlich noch lebendig.

62

Bleibt diese Socket-Verbindung nun für immer offen oder gibt es ein Timeout-Limit, das mit HTTP-Keep-Alive vergleichbar ist?

Die kurze Antwort lautet yes , es gibt eine Zeitüberschreitung und sie wird über TCP Keep-Alive erzwungen.

Wenn Sie das Keep-Alive-Timeout konfigurieren möchten, lesen Sie den folgenden Abschnitt "Ändern von TCP Timeouts".

Einführung

TCP-Verbindungen bestehen aus zwei Sockets, einem an jedem Ende der Verbindung. Wenn eine Seite die Verbindung beenden möchte, sendet sie ein RST -Paket, das die andere Seite bestätigt, und beide schließen ihre Sockets.

Bis dahin lassen beide Seiten ihre Steckdose jedoch auf unbestimmte Zeit offen. Dies lässt die Möglichkeit offen, dass eine Seite ihren Socket absichtlich oder aufgrund eines Fehlers schließt, ohne das andere Ende über RST zu informieren. Um dieses Szenario zu erkennen und veraltete Verbindungen zu schließen, wird der Prozess TCP Keep Alive verwendet.

Keep-Alive-Prozess

Es gibt drei konfigurierbare Eigenschaften, die bestimmen, wie Keep-Alives funktionieren. Unter Linux sind sie1:

  • tcp_keepalive_time
    • standard 7200 Sekunden
  • tcp_keepalive_probes
    • standard 9
  • tcp_keepalive_intvl
    • standard 75 Sekunden

Der Prozess funktioniert wie folgt:

  1. Client öffnet TCP Verbindung
  2. Wenn die Verbindung für tcp_keepalive_time Sekunden still ist, senden Sie ein einzelnes leeres ACK Paket.1
  3. Hat der Server mit einem eigenen ACK geantwortet?
    • Nein
      1. Warten Sie tcp_keepalive_intvl Sekunden und senden Sie dann ein weiteres ACK
      2. Wiederholen, bis die Anzahl der gesendeten ACK Tests gleich tcp_keepalive_probes Ist.
      3. Wenn zu diesem Zeitpunkt keine Antwort eingegangen ist, senden Sie ein RST und beenden Sie die Verbindung.
    • Ja : Kehren Sie zu Schritt 2 zurück

Dieser Vorgang ist auf den meisten Betriebssystemen standardmäßig aktiviert. Daher werden tote TCP Verbindungen regelmäßig getrennt, wenn das andere Ende 2 Stunden und 11 Minuten lang nicht reagiert hat (7200 Sekunden + 75 * 9 Sekunden).

Fallstricke

2 Stunden Standard

Da der Prozess standardmäßig erst gestartet wird, nachdem eine Verbindung zwei Stunden lang inaktiv war, können veraltete TCP Verbindungen sehr lange verweilen, bevor sie gekürzt werden. Dies kann besonders für teure Verbindungen schädlich sein wie Datenbankverbindungen.

Keep-Alive ist optional

Gemäß RFC 1122 4.2.3.6 , Antworten auf und/oder Weiterleiten TCP Keep-Alive-Pakete ist optional:

Implementierer KÖNNEN "Keep-Alives" in ihre TCP) - Implementierungen aufnehmen, obwohl diese Vorgehensweise nicht allgemein akzeptiert wird. Wenn Keep-Alives enthalten sind, MUSS die Anwendung diese für jedes aktivieren oder deaktivieren können TCP Verbindung, und sie müssen standardmäßig ausgeschaltet sein.

...

Es ist äußerst wichtig zu bedenken, dass ACK-Segmente, die keine Daten enthalten, nicht zuverlässig von TCP übertragen werden.

Der Grund dafür ist, dass Keep-Alive-Pakete keine Daten enthalten und nicht unbedingt erforderlich sind und bei übermäßigem Gebrauch die Röhren der Interwebs verstopfen können.

In der Praxis jedoch Ich habe die Erfahrung gemacht, dass diese Sorge im Laufe der Zeit nachgelassen hat, da die Bandbreite billiger geworden ist. und daher werden Keep-Alive-Pakete normalerweise nicht verworfen. Amazon EC2-Dokumentation gibt beispielsweise eine indirekte Bestätigung für Keep-Alive. Wenn Sie also mit AWS hosten, können Sie sich wahrscheinlich auf Keep-Alive verlassen, aber Ihre Meilen können variieren.

Ändern von TCP Timeouts

Pro Sockel

Da TCP -Verbindungen auf Betriebssystemebene verwaltet werden, unterstützt Java keine Zeitüberschreitungen auf Socket-Ebene wie in Java.net.Socket Ich habe einige Versuche gefunden3 Verwenden von Java Native Interface (JNI)) zum Erstellen von Java Sockets, die systemeigenen Code aufrufen, um diese Optionen zu konfigurieren, aber keine davon scheint von der Community allgemein akzeptiert oder unterstützt zu werden.

Stattdessen müssen Sie möglicherweise Ihre Konfiguration auf das gesamte Betriebssystem anwenden. Beachten Sie, dass diese Konfiguration alle TCP Verbindungen betrifft, die auf dem gesamten System ausgeführt werden.

Linux

Die aktuell konfigurierten TCP Keep-Alive-Einstellungen finden Sie in

  • /proc/sys/net/ipv4/tcp_keepalive_time
  • /proc/sys/net/ipv4/tcp_keepalive_probes
  • /proc/sys/net/ipv4/tcp_keepalive_intvl

Sie können eines dieser Updates wie folgt durchführen:

# Send first Keep-Alive packet when a TCP socket has been idle for 3 minutes
$ echo 180 > /proc/sys/net/ipv4/tcp_keepalive_time
# Send three Keep-Alive probes...
$ echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes
# ... spaced 10 seconds apart.
$ echo 10 > /proc/sys/net/ipv4/tcp_keepalive_intvl

Solche Änderungen werden durch einen Neustart nicht beibehalten. Verwenden Sie sysctl, um dauerhafte Änderungen vorzunehmen:

sysctl -w net.ipv4.tcp_keepalive_time=180 net.ipv4.tcp_keepalive_probes=3 net.ipv4.tcp_keepalive_intvl=10

Mac OS X

Die aktuell konfigurierten Einstellungen können mit sysctl angezeigt werden:

$ sysctl net.inet.tcp | grep -E "keepidle|keepintvl|keepcnt"
net.inet.tcp.keepidle: 7200000
net.inet.tcp.keepintvl: 75000
net.inet.tcp.keepcnt: 8

Bemerkenswerterweise definiert Mac OS X keepidle und keepintvl in Einheiten von Millisekunden im Gegensatz zu Linux, das Sekunden verwendet.

Die Eigenschaften können mit sysctl festgelegt werden, wodurch diese Einstellungen auch nach einem Neustart beibehalten werden:

sysctl -w net.inet.tcp.keepidle=180000 net.inet.tcp.keepcnt=3 net.inet.tcp.keepintvl=10000

Alternativ können Sie sie zu /etc/sysctl.conf Hinzufügen (Erstellen der Datei, falls sie nicht vorhanden ist).

$ cat /etc/sysctl.conf
net.inet.tcp.keepidle=180000
net.inet.tcp.keepintvl=10000
net.inet.tcp.keepcnt=3

Windows

Ich habe keinen Windows-Computer zur Bestätigung, aber Sie sollten die entsprechenden TCP Keep-Alive-Einstellungen in der Registrierung unter finden

\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters

Fußnoten

1. Weitere Informationen finden Sie unter man tcp.

2. Dieses Paket wird oft als "Keep-Alive" -Paket bezeichnet, aber innerhalb der TCP) - Spezifikation handelt es sich nur um ein reguläres ACK -Paket. Anwendungen wie Wireshark sind dazu in der Lage Kennzeichnen Sie es als ein "Keep-Alive" -Paket, indem Sie die Sequenz- und Bestätigungsnummern, die es enthält, in Bezug auf die vorhergehenden Kommunikationen auf dem Socket einer Metaanalyse unterziehen.

3. Einige Beispiele, die ich bei einer einfachen Google-Suche gefunden habe, sind lucwilliams/JavaLinuxNet und flonatel/libdontdie .

78
Cory Klein

Sie suchen nach der Socketoption SO_KEEPALIVE.

Die Java Socket-API macht Anwendungen über die Methoden setKeepAlive und getKeepAlive "Keep-Alive" verfügbar. 

EDIT: SO_KEEPALIVE ist in den Netzwerkprotokollstapeln des Betriebssystems implementiert, ohne "echte" Daten zu senden. Das Keep-Alive-Intervall ist vom Betriebssystem abhängig und kann über einen Kernel-Parameter eingestellt werden.

Da keine Daten gesendet werden, kann SO_KEEPALIVE nur die Leistungsfähigkeit der Netzwerkverbindung testen, nicht die Leistungsfähigkeit des Dienstes, mit dem der Socket verbunden ist. Um Letzteres zu testen, müssen Sie etwas implementieren, bei dem Sie Nachrichten an den Server senden und eine Antwort erhalten.

51
Stephen C

TCP-Keepalive und HTTP-Keepalive sind sehr unterschiedliche Konzepte. In TCP ist Keepalive das Verwaltungspaket, das zur Erkennung veralteter Verbindungen gesendet wird. Keepalive bedeutet in HTTP den Status der permanenten Verbindung.

Dies ist aus der TCP Spezifikation,

Keep-Alive-Pakete MÜSSEN nur dann gesendet werden, wenn innerhalb eines Intervalls keine Daten oder Bestätigungspakete für die Verbindung empfangen wurden. Dieses Intervall MUSS konfigurierbar sein und MUSS mindestens zwei Stunden betragen.

Wie Sie sehen, ist das Standard-Keepalive-Intervall TCP für die meisten Anwendungen zu lang. Möglicherweise müssen Sie Keepalive in Ihrem Anwendungsprotokoll hinzufügen.

32
ZZ Coder

Wenn Sie hinter einem Maskerading NAT stehen (wie es heutzutage die meisten Heimanwender sind), gibt es einen begrenzten Pool externer Ports, und diese müssen zwischen den TCP - Verbindungen gemeinsam genutzt werden. Masquerading-NATs gehen daher davon aus, dass eine Verbindung abgebrochen wurde, wenn für einen bestimmten Zeitraum keine Daten gesendet wurden.

Diese und andere derartige Probleme (irgendwo zwischen den beiden Endpunkten) können bedeuten, dass die Verbindung nicht mehr "funktioniert", wenn Sie versuchen, Daten nach einer trägen Leerlaufzeit zu senden. Möglicherweise entdecken Sie dies jedoch erst, wenn Sie mit versuchen Daten senden.

Wenn Sie Keepalives verwenden, wird sowohl (verringert} _ die Wahrscheinlichkeit, dass die Verbindung irgendwo auf der anderen Seite unterbrochen wird, als auch Sie früher über eine unterbrochene Verbindung informiert werden.

21
Artelius

Hier ist eine ergänzende Literatur zu keepalive, die es detaillierter erklärt.

http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO

Da Sie in Java keine Möglichkeit haben, die tatsächlichen Keepalive-Zeiten zu steuern, können Sie diese Beispiele verwenden, wenn Sie einen Linux-Kernel (oder ein proc-basiertes Betriebssystem) verwenden.

4
Jeach

In Java Socket - TCP werden Verbindungen auf Betriebssystemebene verwaltet. Java.net.Socket bietet keine integrierte Funktion zum Festlegen von Timeouts für Keepalive-Pakete auf Socket-Ebene. Wir können jedoch die Keepalive-Option für Java-Socket aktivieren, aber es dauert standardmäßig 2 Stunden 11 Minuten (7200 Sek.), Um nach einer verbrauchten TCP-Verbindung zu verarbeiten. Diese Ursache-Verbindung wird vor der Reinigung sehr lange verfügbar sein. Wir haben also eine Lösung gefunden, um Java Native Interface (JNI) zu verwenden, die nativen Code (C++) zum Konfigurieren dieser Optionen aufruft.

**** Windows OS ****

Im Windows-Betriebssystem keepalive_time & keepalive_intvl kann zwar konfiguriert werden, tcp_keepalive_probes kann jedoch nicht geändert werden. Standardmäßig wird bei der Initialisierung eines TCP - Sockets das Keep-Alive-Timeout auf 2 Stunden und das Keep-Alive-Intervall auf 1 Sekunde gesetzt. Der systemweite Standardwert des Keep-Alive-Timeouts kann über die Registrierungseinstellung KeepAliveTime gesteuert werden, die einen Wert in Millisekunden annimmt.

Unter Windows Vista und höher ist die Anzahl der Keep-Alive-Tests (Neuübertragungen von Daten) auf 10 festgelegt und kann nicht geändert werden.

Für Windows Server 2003, Windows XP und Windows 2000 ist die Standardeinstellung für die Anzahl der Keep-Alive-Probes 5. Die Anzahl der Keep-Alive-Probes ist steuerbar. Für Windows wird die Winsock-Bibliothek IOCTLs verwendet, um die Parameter für tcp-keepalive zu konfigurieren.

int WSAIoctl (SocketFD, // Deskriptor, der einen Socket identifiziert SIO_KEEPALIVE_VALS, // dwIoControlCode (LPVOID) lpvInBuffer, // Zeiger auf tcp_keepalive struct (DWORD) cbInBuffer, // Länge des Eingabepuffers NULL, // Ausgabepuffer 0 // Größe des Ausgabepuffers (LPDWORD) lpcbBytesReturned, // Anzahl der zurückgegebenen Bytes NULL, // OVERLAPPED-Struktur NULL // Beendigungsroutine);

Linux OS

Linux bietet eine integrierte Unterstützung für Keepalive, die zur Nutzung von TCP/IP-Netzwerken erforderlich ist. Programme müssen über die Setsockopt-Schnittstelle eine Keepalive-Steuerung für ihre Sockets anfordern.

int setsockopt (int-Socket, int-Ebene, int optname, const void * optval, socklen_t optlen)

Jeder Client-Socket wird mit Java.net.Socket erstellt. Die Datei-Deskriptor-ID für jeden Socket wird mithilfe von Java-Reflection abgerufen.

0

Für Windows nach Microsoft-Dokumenten

  • KeepAliveTime (REG_DWORD, Millisekunden, standardmäßig nicht gesetzt, dh 7.200.000.000 = 2 Stunden) - analog zu tcp_keepalive_time
  • KeepAliveInterval (REG_DWORD, Millisekunden, standardmäßig nicht gesetzt, dh 1.000 = 1 Sekunde) - analog zu tcp_keepalive_intvl
  • Da es in Windows Vista kein analoges zu tcp_keepalive_probes gibt, ist der Wert auf 10 festgelegt und kann nicht geändert werden
0
semen