Versuchsaufbau:
Ein TCP-Klient (tcpcli.c) auf Rechner kirke (IP-Adresse 134.109.192.39, Betriebssystem Linux 2.0.33) kommuniziert mit einem TCP-Server (tcpserv.c) am Port 5000 auf Rechner yang (IP-Adresse 134.109.184.150, Betriebssystem Solaris 2.5.1). Nach dem Verbindungsaufbau werden zwischen Server und Klient je eine Nachricht und eine zugehörige Bestätigung ausgetauscht. Danach unterbrechen wir die Verbindung softwaremäßig durch Entfernen der Default-Route aus der Routing-Tabelle der kirke.
Um die Manipulation der Routing-Tabelle zu vereinfachen, definieren wir uns zunächst drei Kommandos:
root@kirke 1 # alias show 'route -n' root@kirke 2 # alias del 'route delete default' root@kirke 3 # alias add 'route add default gw 134.109.192.254'Die Routing-Tabelle der kirke sieht zunächst so aus:
root@kirke 4 # show Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 134.109.192.0 0.0.0.0 255.255.255.0 U 0 0 11 eth0 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 2 lo 0.0.0.0 134.109.192.254 0.0.0.0 UG 0 0 1 eth0Die Steuerung des Experiments kann auch nach dem Löschen der Default-Route problemlos von der kirke aus erfolgen, da diese z.B. über die im gleichen Subnetz befindliche ultra (IP-Adresse 134.109.192.89) den yang erreicht.
Der Standardwert des Keepalive-Timers beträgt bei Solaris 2.5.1 zwei Stunden (7200 Sekunden bzw. 7.200.000 Millisekunden). Vor dem Experiment wird dieser Wert auf 10 Sekunden reduziert:
ROOT@yang 1 # ndd -set /dev/tcp tcp_keepalive_interval 10000Das Kommando ndd ist Solaris-spezifisch und gestattet zur Laufzeit die Einstellung bestimmter Parameter von im Systemkern enthaltenen Treibern. Der Wert 10000 ist der Minimalwert für das Intervall des Keepalive-Timers. Kleinere Zahlen werden mit der Meldung operation failed, Invalid argument zurückgewiesen.
Die gesamte Kommunikation zwischen kirke und yang wird mittels snoop auf dem yang aufgezeichnet:
ROOT@yang 2 # snoop -o dump host yang and port 5000
Nun wollen wir also mal sehen, wie Solaris auf eine unterbrochene Verbindung reagiert. Zuerst wird unser Server gestartet:
hot@yang 1 > ./tcpserv -k 5000Bei noch existierender Default-Route lassen wir den Klienten eine Nachricht senden:
hot@kirke 10 > ./tcpcli yang 5000 Nachricht: eins Nachricht:Der Server bekommt diese Nachricht ordnungsgemäß:
hot@yang 1 > ./tcpserv -k 5000 Option SO_KEEPALIVE hat Wert 8 und Laenge 4 1 Byte an Klienten gesendet; zum Test auf SIGPIPE (sollte hier nicht passieren) Nachricht der Laenge 4: einsDer Server sendet vor dem Empfang der ersten Nachricht des Klienten an diesen ein Byte, um zu zeigen, daß die Ausgabe-Operation kein Signal SIGPIPE generiert, wie das später nach den Keepalive-Probes der Fall sein wird.
Nun entfernen wir die Default-Route der kirke:
root@kirke 5 # del root@kirke 6 # show Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 134.109.192.0 0.0.0.0 255.255.255.0 U 0 0 11 eth0 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 2 loMittels ping können wir uns sehr leicht davon überzeugen, daß jetzt keine IP-Pakete mehr zum yang durchkommen:
root@kirke 7 # ping yang PING yang.informatik.tu-chemnitz.de (134.109.184.150): 56 data bytes ping: sendto: Network is unreachable ping: wrote yang.informatik.tu-chemnitz.de 64 chars, ret=-1 ping: sendto: Network is unreachable ping: wrote yang.informatik.tu-chemnitz.de 64 chars, ret=-1 ... --- yang.informatik.tu-chemnitz.de ping statistics --- 18 packets transmitted, 0 packets received, 100% packet lossJetzt schlägt auch das Senden einer weiteren Nachricht fehl. Der Server bekommt davon natürlich überhaupt nichts mit:
hot@kirke 16 > ./tcpcli yang 5000 Nachricht: eins Nachricht: zwei write socket: Host is unreachable Nachricht:Nun gut. Warten wir geduldig ab, was passiert. Der Paket-Zähler von snoop läßt erkennen, daß trotz der logisch unterbrochenen Verbindung Pakete gesendet werden. Der Keepalive-Timer muß also bereits aktiv geworden sein.
snoop zeigt an, daß yang nach dem Austausch von insgesamt 15 Paketen aufgibt:
ROOT@yang 2 # snoop -o dump proto tcp host yang and port 5000 Using device /dev/le (promiscuous mode) 15Der Server kehrte aus seinem blockierenden read() mit dem Fehlercode Connection timed out zurück. Die Verbindung wurde durch den Solaris-Kern automatisch abgebrochen. Das erkennt man an dem Signal SIGPIPE, das beim Versuch, auf den Socket zu schreiben, generiert wird:
hot@yang 1 > ./tcpserv -k 5000 Option SO_KEEPALIVE hat Wert 8 und Laenge 4 1 Byte an Klienten gesendet; zum Test auf SIGPIPE (sollte hier nicht passieren) Nachricht der Laenge 4: eins read socket: Connection timed out SIGPIPE abgefangen msgsock geschlossen EndeAls die Verbindung noch existierte, verlief die gleiche Schreiboperation erfolgreich.
Der folgende Snoop-Mitschnitt zeigt den gesamten Verlauf bis zum Verbindungsabbruch sehr anschaulich:
1 0.00000 kirke -> yang TCP D=5000 S=1105 Syn Seq=3147275981 Len=0 Win=512 2 0.00076 yang -> kirke TCP D=1105 S=5000 Syn Ack=3147275982 Seq=528934210 Len=0 Win=64240 3 0.00293 kirke -> yang TCP D=5000 S=1105 Ack=528934211 Seq=3147275982 Len=0 Win=32120 4 0.00570 yang -> kirke TCP D=1105 S=5000 Ack=3147275982 Seq=528934211 Len=1 Win=64240 5 0.01798 kirke -> yang TCP D=5000 S=1105 Ack=528934212 Seq=3147275982 Len=0 Win=32120 6 6.14229 kirke -> yang TCP D=5000 S=1105 Ack=528934212 Seq=3147275982 Len=5 Win=32120 7 0.04484 yang -> kirke TCP D=1105 S=5000 Ack=3147275987 Seq=528934212 Len=0 Win=64240 8 12.54995 yang -> kirke TCP D=1105 S=5000 Ack=3147275987 Seq=528934211 Len=1 Win=64240 9 1.46990 yang -> kirke TCP D=1105 S=5000 Ack=3147275987 Seq=528934211 Len=1 Win=64240 10 2.93003 yang -> kirke TCP D=1105 S=5000 Ack=3147275987 Seq=528934211 Len=1 Win=64240 11 5.85005 yang -> kirke TCP D=1105 S=5000 Ack=3147275987 Seq=528934211 Len=1 Win=64240 12 11.69996 yang -> kirke TCP D=1105 S=5000 Ack=3147275987 Seq=528934211 Len=1 Win=64240 13 23.40000 yang -> kirke TCP D=1105 S=5000 Ack=3147275987 Seq=528934211 Len=1 Win=64240 14 46.80002 yang -> kirke TCP D=1105 S=5000 Ack=3147275987 Seq=528934211 Len=1 Win=64240 15 56.25079 yang -> kirke TCP D=1105 S=5000 Ack=3147275987 Seq=528934211 Len=1 Win=64240Für mehr Details stehen die Ausgaben des Verbose Mode sowie des Verbose Summary Mode zur Verfügung.
Die erste Keepalive-Probe (Paket 8) folgt ca. 12,5 Sekunden nach der letzten regulären Bestätigung (Paket 7). Die Abstände zwischen den Probes wachsen zunehmend bis zu einem Maximum von ca. 56 Sekunden:
Wiederholung der Keepalive-Probe | Abstand in Sekunden |
---|---|
1 | 1.46990 |
2 | 2.93003 |
3 | 5.85005 |
4 | 11.69996 |
5 | 23.40000 |
6 | 46.80002 |
7 | 56.25079 |
Wie wir sehen, spielen hier die bei Stevens in TCP/IP Illustrated Vol. I angegebenen 75 Sekunden keine Rolle. Nach insgesamt 8 Keepalive-Probes gab Solaris in unserem Beispiel auf, wobei statt einer zahlenmäßigen auch eine zeitliche Obergrenze überschritten worden sein kann.
Nach dem Abbruch der Verbindung sendet der Server kein FIN- oder RST-Segment, was ja auch keinen Sinn machen würde, da der Klient nicht erreichbar ist.