Ist es möglich, Java-Sockets sowohl auf Client- als auch auf Serverseite zu schließen?

7

Ich habe eine Socket-TCP-Verbindung zwischen zwei Java-Anwendungen. Wenn eine Seite die Steckdose schließt, bleibt die andere Seite offen. aber ich möchte, dass es geschlossen wird. Und ich kann auch nicht darauf warten, ob es verfügbar ist oder nicht und danach schließen. Ich möchte einen Weg, um es komplett von einer Seite zu schließen. Was kann ich tun?

    
Shayan 29.01.2010, 22:33
quelle

5 Antworten

10

TCP funktioniert nicht so. Das Betriebssystem gibt die Ressourcen, nämlich den Dateideskriptor und somit den Port nicht frei, bis die Anwendung den Socket oder die Dies explizit schließt, selbst wenn der TCP-Stack weiß, dass die andere Seite ihn geschlossen hat. Es gibt keinen Rückruf vom Kernel zur Benutzeranwendung beim Empfang des FIN vom Peer. Das Betriebssystem bestätigt dies der anderen Seite, wartet jedoch darauf, dass die Anwendung close() aufruft, bevor sie ihr FIN-Paket sendet. Werfen Sie einen Blick auf das TCP-Zustandsübergangsdiagramm - Sie sind im Feld passiv schließen .

Eine Möglichkeit, eine Situation wie diese zu erkennen, ohne jedem Thread einen Thread zuzuweisen, ist die Verwendung der Funktionsfamilie select/poll/epoll/kqueue . Der passiv geschlossene Socket wird als lesbar gemeldet und der Leseversuch gibt den EOF zurück.

Hoffe, das hilft.

    
Nikolai Fetissov 30.01.2010, 03:31
quelle
6

Beide Seiten müssen von der Verbindung lesen, damit sie erkennen können, wann der Peer geschlossen wurde. Wenn read -1 zurückgibt, bedeutet dies, dass das andere Ende die Verbindung geschlossen hat und das ist dein Schlüssel, um dein Ende zu schließen.

    
nos 29.01.2010 22:40
quelle
4

Wenn Sie immer noch von Ihrem Socket lesen, werden Sie beim Schließen die -1 erkennen.

Wenn Sie nicht mehr von Ihrem Sockel lesen, gehen Sie weiter und schließen Sie es.

Wenn es keines von beiden gibt, wartet wahrscheinlich ein Thread auf ein Ereignis. Dies ist NICHT die Art, wie Sie Tausende von Ports behandeln möchten! Java wird in etwa 3000 Threads in Windows pukey bekommen - viel weniger in Linux (ich weiß nicht warum).

Stellen Sie sicher, dass Sie NIO verwenden. Verwenden Sie einen einzelnen Thread, um alle Ihre Ports zu verwalten (Verbindungspool). Es sollte nur die Daten aus einem Thread abrufen und an eine Warteschlange weiterleiten. An diesem Punkt würde ich einen Thread-Pool haben, der die Daten aus den Warteschlangen holt und verarbeitet, weil die Verarbeitung der Daten von einem Port einige Zeit dauern wird.

Das Anhängen eines Threads an jeden Port funktioniert NICHT und ist der Hauptgrund, warum NIO benötigt wurde.

Wenn Sie eine Art "Schließen" -Meldung als Teil Ihres Streams zum Auslösen des Schließens des Ports verwenden, können die Dinge möglicherweise schneller funktionieren - Sie müssen jedoch immer noch die -1 behandeln, um den Fall von fehlerhaften Streams zu behandeln / p>     

Bill K 29.01.2010 22:53
quelle
3

Die übliche Lösung besteht darin, die andere Seite wissen zu lassen, dass Sie die Verbindung schließen werden, bevor Sie sie tatsächlich schließen. Im Fall des SMTP-Protokolls sendet der Server zum Beispiel "221 Bye", bevor er die Verbindung schließt.

    
Confusion 29.01.2010 22:57
quelle
0

Sie möchten wahrscheinlich einen Verbindungspool haben.

    
Roman 29.01.2010 22:48
quelle

Tags und Links