2009-01-09 3 views
6

Wenn ich öffne und eine Steckdose in die Nähe zum Beispiel AufrufGibt es ein Datei-Deskriptor-Leck, wenn Sockets auf einer Linux-Plattform verwendet werden?

Socket s = new Socket(...); 
s.setReuseAddress(true); 
in = s.getInputStream(); 
... 
in.close(); 
s.close();  

Linux stellt fest, dass diese Fassung noch offen ist oder zumindest der Dateideskriptor für die Verbindung ist presen. Wenn für diesen Prozess durch lsof die geöffneten Dateien abfragen, gibt es einen Eintrag für die geschlossene Verbindung:

COMMAND PID USER FD TYPE DEVICE  SIZE NODE NAME 
java 9268 user 5u sock 0,4   93417 can't identify protocol 

Dieser Eintrag bleibt, bis das Programm geschlossen wird. Gibt es einen anderen Weg, um den Sockel endlich zu schließen? Ich bin ein wenig besorgt, dass meine Java-Anwendung zu viele Dateideskriptoren blockieren kann. Ist das möglich? Oder behält Java diese Sockets, um sie wiederzuverwenden, selbst wenn ReuseAddress gesetzt ist?

Antwort

5

Wenn diese Buchsen alle im TIME_WAIT-Zustand sind, ist dies zumindest für eine kurze Zeit normal. Überprüfen Sie das mit Netstat; Es ist üblich, dass Sockets für einige Minuten herumhängen, um sicherzustellen, dass verstreute Daten aus dem Socket erfolgreich verworfen werden, bevor der Port für einen neuen Socket wiederverwendet wird.

+0

Einverstanden - dies ist die erste zu überprüfende Sache. Und nach ein paar Minuten sollten die Sockets verschwinden, bevor Ihr Programm beendet wird. –

+0

Der Autor sagt, dass die Einträge bleiben, bis das Programm schließt, obwohl ich denke, er gibt nicht an, ob das mehr als ein paar Minuten ist. –

+0

Ja, ich sah das "Programm schließt" -Bit, war mir aber nicht sicher. –

0

Vielleicht ist es ein Socket eines anderen Protokolls ("Kann Protokoll nicht identifizieren" eh?) Intern in der Implementierung verwendet, um etwas zu tun, die auf dem ersten Sockel erstellt wird.

Haben Sie wiederholt versucht, Sockets zu erstellen und sie zu schließen, um zu sehen, ob diese Sockets wirklich bestehen bleiben? Es scheint wahrscheinlich, dass dies eine einmalige Sache ist.

Java benutzt wahrscheinlich Sockets intern für viele Dinge - sie könnten Unix, Netlink (unter Linux) oder eine andere Art von Socket sein.

0

Erstellen Sie ein kleines Bash-Skript, um geöffnete Sockets für eine bestimmte App oder PID zu überwachen, und lassen Sie es laufen, während Sie Ihre Java-App testen.

Ich bezweifle sowieso, dass es irgendeine Art von Lecks in dieser Sache als Steckdosen sehr verwendet in Linux/Unix-Welt und diese Art von Problem würde sprudelt sehr quicky

3

Sie auch /proc/<pid>/fd überprüfen mögen, die Verzeichnis enthält alle aktuell geöffneten Dateideskriptoren. Wenn eine Datei verschwindet, nachdem Sie den Socket geschlossen haben, werden Sie keine Probleme mehr haben (zumindest nicht mit Ihren Dateideskriptoren :).

1

Ich denke, es ist nicht das Problem Ihres Programms.

In SUN_Java, wenn sockelbezogene native lib geladen ist, wird ein MAGIC_SOCK fd erstellt.

Schreiben auf die MAGIC_SOCK wird eine Connect Rest Exception ergeben, und lesen auf der MAGIC_SOCK wird ein EOF ergeben.

Der Peer des magic_sock wurde vollständig geschlossen, und der magic_sock selbst ist halb_geschlossen und der Status bleibt "Protokoll kann nicht identifiziert werden".