Ich habe diese verdammte Struktur:
%Vor%Wie Sie sehen können, muss ich den Listener genauso schließen wie beim Socket. Das Problem ist, dass, wenn ich versuche, dies nach der Schleife zu tun, der Code "unerreichbar" ist, und wenn ich versuche, irgendwo ein Feld für den ServerSocket zu deklarieren, bekomme ich eine NullPointerException. Ich möchte den ServerSocket nicht zusammen mit dem Socket / Client schließen, da ich neue Verbindungen aufbauen möchte.
Also das ist meine Frage:
Es ist wirklich notwendig, den ServerSocket in diesem Fall zu schließen? Der ServerSocket schließt sich selbst, wenn die Software heruntergefahren wird? (System.exit (0)) . Wenn der ServerSocket weiterhin läuft, wenn ich die Software schließe, nur weil ich sie nicht geschlossen habe, dann habe ich ein Problem, weil ich diesen blutigen Code nicht erreichen kann, um ihn zu schließen:).
Ja. Beim Löschen von Verweisen auf den Socket kann dazu führen, dass der Garbage Collector den Abschluss finalisiert, bedeutet dies nicht, dass er geschlossen wird. Dies ist in vielen Fällen implementierungsspezifisch und kann manchmal aufgrund von Performance oder sogar kleinen Fehlern, die schwer zu verfolgen sind, relativ zum Design entgleisen.
Eine Referenz irgendwo zu halten ist eine sichere Wette, die auch bei schwachenReferenzen nicht möglich ist.
Jetzt hat das Betriebssystem eine (aufgrund seines Designs) begrenzte Anzahl an Sockeln, die es geben kann. Wenn Sie mehr und mehr Sockets öffnen, gerät das Betriebssystem unter Druck und es laufen keine Sockets mehr, was zum Ausfall von Java oder einem anderen Programm führt. Abhängig von den Socket-Optionen, die Sie oder die Standardeinstellungen festlegen, sendet dieser Socket möglicherweise auch Keepalives und verbraucht Ressourcen auf dem anderen Endpunkt.
Beim Beenden wird es vom Socket geschlossen, der eine Shutdown-Aktion in seinem Konstruktor registriert, um sie zu schließen, und / oder die automatische Bereinigung des Betriebssystems.
Sie sollten sich nie auf das OS / JVM-Verhalten oder die Finalisierung verlassen, um Ihre Sockets zu schließen, besonders wenn Sie mehrere Sockets haben, auch wenn Sie nicht alle verwenden möchten von ihnen zur gleichen Zeit.
Ja, es ist notwendig, irgendwelche endlichen Ressourcen freizugeben, da Ihre App andernfalls andere Prozesse auf dem Host nach Ressourcen hungern lässt und nicht in der Lage ist, auf lange Sicht zu überleben
So mache ich eine solche Aufgabe:
%Vor%Außerdem wäre es eine gute Idee, GUI-Code in andere Klassen zu verschieben, um die Dinge sauber zu halten.
Eine Antwort ist, dass Sie wirklich close()
Ressourcen verwenden sollten ... auch wenn es nicht unbedingt notwendig ist.
Warum?
Weil die Umstände, die (hypothetisch) bedeuten, dass es nicht unbedingt notwendig ist, ändern könnten!
Und ... seien wir ehrlich ... es ist einfach Code zu schreiben, um einen Server-Socket automatisch zu schließen.
Aber lesen Sie weiter ...
Es ist wirklich notwendig, den ServerSocket in diesem Fall zu schließen?
Kommt darauf an.
Wenn Sie sicher wissen , dass run()
nur einmal ausgeführt wird und die Anwendung dann immer vollständig heruntergefahren wird (Modulo-Einschränkungen unten), dann wird die Anwendung nicht geschlossen ServerSocket
verursacht keinen tatsächlichen Schaden.
Andernfalls könnte das Schließen von () zu zu Schäden führen.
Der "Schaden" könnte verschiedene Formen annehmen:
Der Server-Socket könnte eine "Sperre" für einen Port enthalten, wodurch verhindert wird, dass eine andere Instanz der Anwendung diesen Port abhört (abhängig vom Betriebssystem).
Der Server-Socket könnte eine begrenzte Ressource sein, und wenn die Methode run()
mehrere Male aufgerufen wird (ohne close()
-ing), könnte die Anwendung alle verfügbaren Instanzen dieser Ressource "greifen" und andere Anwendungen verhindern vom Erwerb einer Instanz.
Der Schaden könnte auch der Anwendungsinstanz selbst zugefügt werden, wenn run()
mehrere Male aufgerufen wird.
Der ServerSocket schließt sich selbst, wenn die Software heruntergefahren wird?
Der ServerSocket schließt sich nicht selbst, es sei denn, es wird Müll gesammelt und finalisiert. Und Sie können sich nicht darauf verlassen, dass dies passiert, wenn eine JVM beendet wird. Aber im weiteren Sinne wird die zugrunde liegende Server-Socket-Ressource normalerweise automatisch geschlossen (freigegeben), wenn die JVM beendet wird.
Aber die vollständige Antwort hängt tatsächlich davon ab, was Sie unter "die Software ist heruntergefahren" und auch von der Art der Plattform verstehen. Zum Beispiel:
Wenn shutdown bedeutet, dass die JVM vollständig beendet wird und der entsprechende Prozess, der den zugrundeliegenden Server-Socket (aus der Sicht des Betriebssystems) " auch " besitzt ", dann schließt das Betriebssystem diesen Socket ... zumindest auf modernen Unix / Linux / Windows-Plattformen. (Beachten Sie, dass Android Linux unter der Haube ist)
Wenn "die Software" so etwas wie eine in einem Webcontainer ausgeführte Webanwendung ist, kann das "Herunterfahren" etwas anderes als den JVM-Exit bedeuten, und der ServerSocket könnte nach dem Herunterfahren weiter bestehen (und nicht geschlossen sein) .
Wenn die JVM in etwas anderes eingebettet ist (zB in einer großen C / C ++ - Anwendung) und etwas anderes nicht beendet wird, weiß das Betriebssystem nicht, dass es den darunterliegenden Server-Socket freigibt.
>Wenn Sie auf einer Plattform arbeiten, auf der das Betriebssystem nicht das gleiche Maß an Prozesstrennung / Ressourcenverwaltung bietet wie unter Unix / Linux / (modern) Windows, dann ist der zugrunde liegende Server-Socket möglicherweise nicht wird vom Betriebssystem beim Beenden des Prozesses geschlossen. (Dieses Szenario könnte für eine Java-Implementierung auf einem eingebetteten System gelten ...)
Auf jeden Fall ist es nicht schwer, das Richtige zu tun. In Java 7 und später:
%Vor% (Ich sehe jedoch nicht den Punkt, an dem HeadlessException
in einer scheinbar von einem Tasten-Listener aufgerufenen Aktion abgefangen wird.)
Tags und Links java serversocket