2013-04-09 12 views
56

Ich habe ein kleines Programm geschrieben, das mit einem Server an einem bestimmten Port interagiert. Das Programm funktioniert gut, aber:Wie entferne ich eine CLOSE_WAIT Socket-Verbindung

Sobald das Programm unerwartet beendet, und seit dieser Socket-Verbindung wird in CLOSE_WAIT Zustand angezeigt. Wenn ich versuche, ein Programm zu starten, hängt es und ich muss es schließen, was sogar mehrCLOSE_WAIT Socket-Verbindungen erzwingt.

Gibt es eine Möglichkeit, diese Verbindungen zu spülen?

+2

Sie können nicht (und sollten nicht). CLOSE_WAIT ist ein durch TCP definierter Zustand für Verbindungen, die geschlossen werden und darauf warten, dass das Gegenstück dies bestätigt. – vonbrand

+0

Siehe auch http://unix.stackexchange.com/questions/10106/orphaned-connections-in-close-wait-state ... welches ich nicht als Duplikat wählen werde, weil es die Frage beenden würde als Off-Thema. – derobert

+3

@vonbrand Nein ist es nicht, es ist genau das Gegenteil. Es ist der Status für eine Verbindung, die bereits vom Peer geschlossen wurde und auf das Schließen der lokalen Anwendung wartet. – EJP

Antwort

49

CLOSE_WAIT bedeutet, dass Ihr Programm noch läuft und den Socket nicht geschlossen hat (und der Kernel wartet darauf). Fügen Sie -p zu netstat hinzu, um die PID zu erhalten, und töten Sie sie dann stärker (mit SIGKILL, falls erforderlich). 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, so gilt hier nicht.

+1

gut ... kiling der Prozess möglicherweise nicht die beste, wenn das Programm eine Menge Verbindung zu öffnen, nur ein paar von denen bleiben in "CLOSE_WAIT": in diesem Fall kann das Beenden des Prozesses völlig unmöglich oder unangemessen sein (das Programm funktioniert immer noch und bietet Dienste, mit diesen anderen Verbindungen). Es wäre viel angemessener, die ausstehende Verbindung zu schließen. aber in der Tat ist es normalerweise das Programm selbst, das nicht lokal die Verbindung schließt (CLOSE_WAIT bedeutet, dass es 'FIN' vom anderen Ende empfangen hat und das Programm die Verbindung nur lokal schließen muss). Ein Fehlerbericht kann angebracht sein –

5

Ich habe auch das gleiche Problem mit einem sehr aktuellen Tomcat-Server (7.0.40). Es reagiert ein paar Tage lang nicht mehr.

Um offene Verbindungen zu sehen, können Sie verwenden:

sudo netstat -tonp | grep jsvc | grep --regexp="127.0.0.1:443" --regexp="127.0.0.1:80" | grep CLOSE_WAIT 

Wie in this post erwähnt, Sie /proc/sys/net/ipv4/tcp_keepalive_time verwenden, um die Werte anzuzeigen. 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` 
+3

die Antwort ist verwirrend. Du hast gesagt, dass die nicht-reagierenden Zustände seit einigen Tagen verschwunden sind. Aber dann versuchst du auch, die Keep-Alive-Zeit auf nur 120 Sekunden zu setzen. Selbst mit dem Standardwert (7200 sec) sollte es nicht für mehrere Tage dauern, oder? – fanchyna

27

Wie Crist Clark beschrieben.

CLOSE_WAIT bedeutet, dass das lokale Ende der Verbindung eine FIN vom anderen Ende empfangen hat, aber das Betriebssystem für das Programm an dem lokalen Ende wartet, um tatsächlich seine Verbindung zu schließen.

Das Problem ist, dass Ihr Programm auf dem lokalen Rechner nicht den Socket zu schließen. Es ist kein TCP-Tuning-Problem. Eine Verbindung kann (und ganz richtig) für immer in CLOSE_WAIT bleiben, während das Programm die Verbindung offen hält.

Sobald das lokale Programm den Socket schließt, kann das Betriebssystem das FIN an das entfernte Ende senden, das Sie an LAST_ACK übergibt, während Sie auf das ACK des FIN warten. Sobald dies erreicht ist, ist die Verbindung beendet und fällt aus der Verbindungstabelle (wenn Ihr Ende in CLOSE_WAIT ist, werden Sie tun nicht im TIME_WAIT Zustand enden).

+2

wie man den Sockel schließt ?? –

+0

Schließen Sie den Griff, den Sie an den von Ihnen geöffneten Sockel haben. Verwenden Sie 'close()' oder 'closesocket()', je nachdem, welche Plattform Sie verwenden. –

4

Obwohl zu viele CLOSE_WAIT-Verbindungen bedeuten, dass mit dem Code in der ersten Zeile etwas nicht stimmt und dies wird nicht als gute Praxis akzeptiert.

Vielleicht möchten, um überprüfen: https://github.com/rghose/kill-close-wait-connections

Was dieses Skript tut, ist die ACK senden, die die Verbindung wartete.

Das hat bei mir funktioniert.

+0

senden Sie Akt an Close-Wait-Socket. mit funktioniert nicht .. wenn funktioniert, warum? – Chinaxing

+0

Ich vermute, das Betriebssystem hat das FIN bereits an den Remote-Host gesendet. Der Remote-Host kann wahrscheinlich nicht mit der ACK antworten, die der Socket erwartet. – mirage

+0

Ja, das stimmt (aus Kernel-Code). aber ich bezweifle auch die SEQ des Pakets, das du sendest, das ist "10", überprüft der Kernel es nicht? – Chinaxing