it-swarm.com.de

Wie entferne ich eine CLOSE_WAIT-Socket-Verbindung?

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?

69
Dilletante

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.

59
derobert

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).

31
user2618402

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.

7
mirage

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`
5
Amil Waduwawara

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.

0
Binita Bharati