Ich habe ein kleines Programm geschrieben, das mit einem Server an einem bestimmten Port interagiert. Das Programm funktioniert gut, aber:
Sobald das Programm unerwartet beendet wurde und seit dieser Socket-Verbindung im CLOSE_WAIT
-Status angezeigt wird. Wenn ich versuche, ein Programm auszuführen, hängt es und ich muss es zum Schließen zwingen, wodurch sogar more CLOSE_WAIT
Socket-Verbindungen anfallen.
Gibt es eine Möglichkeit, diese Verbindungen zu spülen?
CLOSE_WAIT
bedeutet, dass Ihr Programm noch läuft und der Socket nicht geschlossen wurde (und der Kernel wartet darauf, dass dies geschieht). Fügen Sie -p
zu netstat
hinzu, um die PID zu erhalten, und töten Sie sie dann kräftiger (ggf. mit SIGKILL
). Das sollte Ihre CLOSE_WAIT
Sockets loswerden. Sie können auch ps
verwenden, um die PID zu finden.
SO_REUSEADDR
ist für Server und TIME_WAIT
-Sockets, hier also nicht zutreffend.
Wie von Crist Clark beschrieben.
CLOSE_WAIT bedeutet, dass das lokale Ende der Verbindung ein .__ erhalten hat. FIN vom anderen Ende, aber das Betriebssystem wartet auf das Programm am lokales Ende, um die Verbindung tatsächlich zu schließen.
Das Problem ist, dass das auf dem lokalen Computer ausgeführte Programm nicht .__ ist. Steckdose schließen. Es ist kein TCP - Abstimmungsproblem. Eine Verbindung kann (und ganz richtig) bleibt für immer in CLOSE_WAIT, solange das Programm hält die Verbindung offen.
Sobald das lokale Programm den Socket schließt, kann das Betriebssystem die FIN an .__ senden. das entfernte Ende, das Sie zu LAST_ACK überführt, während Sie auf .__ warten. das ACK der FIN. Sobald dies erfolgt ist, ist die Verbindung beendet und fällt aus der Verbindungstabelle (wenn sich Ihr Ende in CLOSE_WAIT befindet, landen Sie do not im Zustand TIME_WAIT).
Auch wenn zu viele CLOSE_WAIT-Verbindungen bedeuten, dass in Ihrem ersten Code etwas nicht stimmt, und dies ist keine gute Praxis.
Vielleicht möchten Sie einen Blick darauf werfen: https://github.com/rghose/kill-close-wait-connections
Dieses Skript sendet das ACK aus, auf das die Verbindung gewartet hat.
Das hat bei mir funktioniert.
Ich habe auch das gleiche Problem mit einem neuesten Tomcat-Server (7.0.40). Es reagiert einmal für ein paar Tage nicht.
Um offene Verbindungen anzuzeigen, können Sie Folgendes verwenden:
Sudo netstat -tonp | grep jsvc | grep --regexp="127.0.0.1:443" --regexp="127.0.0.1:80" | grep CLOSE_WAIT
Wie in diesem Beitrag erwähnt, können Sie die Werte mit /proc/sys/net/ipv4/tcp_keepalive_time
anzeigen. Der Wert scheint in Sekunden zu liegen und beträgt standardmäßig 7200 (d. H. 2 Stunden).
Um sie zu ändern, müssen Sie /etc/sysctl.conf
bearbeiten.
Open/create `/etc/sysctl.conf`
Add `net.ipv4.tcp_keepalive_time = 120` and save the file
Invoke `sysctl -p /etc/sysctl.conf`
Verify using `cat /proc/sys/net/ipv4/tcp_keepalive_time`
Es sollte erwähnt werden, dass die Socket
-Instanz sowohl auf dem Client als auch auf dem Serverende close()
explizit aufrufen muss. Wenn nur eines der Enden close()
aufruft, bleibt der Socket auch im Zustand CLOSE_WAIT.