2009-07-25 9 views
61

Für einige meiner Java NIO-Verbindungen, wenn ich einen SocketChannel.write(ByteBuffer) Aufruf habe, wirft es eine IOException: "Gebrochene Leitung".Java NIO: Was bedeutet IOException: Broken Pipe bedeuten?

Was verursacht ein "gebrochenes Rohr" und, was noch wichtiger ist, ist es möglich, von diesem Zustand zu erholen? Wenn es nicht wiederhergestellt werden kann, scheint dies ein gutes Zeichen zu sein, dass ein irreversibles Problem aufgetreten ist und ich diese Socket-Verbindung einfach schließen sollte. Ist das eine vernünftige Annahme? Gibt es jemals eine Zeit, in der diese IOException auftreten würde, während die Socket-Verbindung immer noch richtig verbunden ist (anstelle einer funktionierenden Verbindung, die irgendwann fehlgeschlagen ist)?

Auf einer Seite zur Kenntnis, ist es ratsam, immer SocketChannel.isConnected() aufrufen, bevor eine SocketChannel.write() versuchen, und wenn ja, kann ich auch davon ausgehen, dass die Verbindung „gebrochen“ und sollte geschlossen werden, wenn beide SocketChannel.isConnected() und SocketChannel.isConnectionPending() beide false sind?

Danke!

Antwort

18

Defekte Leitung bedeutet einfach, dass die Verbindung fehlgeschlagen ist. Es ist vernünftig anzunehmen, dass dies nicht behebbar ist, und dann alle erforderlichen Bereinigungsaktionen durchzuführen (Verbindungen schließen usw.). Ich glaube nicht, dass Sie das jemals einfach sehen würden, weil die Verbindung noch nicht abgeschlossen ist.

Wenn Sie den nicht blockierenden Modus verwenden, gibt die Methode SocketChannel.connect den Wert false zurück, und Sie müssen die Methoden isConnectionPending und finishConnect verwenden, um sicherzustellen, dass die Verbindung hergestellt wurde. Ich würde im Allgemeinen Code basierend auf der Erwartung, dass die Dinge funktionieren werden, und dann Ausnahmen abfangen, um Fehler zu erkennen, anstatt sich auf häufige Aufrufe von "isConnected" zu verlassen.

+0

Sie können kein kaputtes Rohr erhalten, ohne vorher ein Rohr zu haben. Sie können keine fehlgeschlagene Verbindung erhalten, ohne zuvor eine Verbindung hergestellt zu haben. Der letzte Absatz dieser Antwort ist korrekt, aber irrelevant. – EJP

1

Sie sollten davon ausgehen, dass die Buchse am anderen Ende geschlossen war. Umschließen Sie Ihren Code mit einem try-catch-Block für IOException.

Sie können isConnected() verwenden, um festzustellen, ob der SocketChannel verbunden ist oder nicht, aber das kann sich ändern, bevor der Aufruf von write() beendet wird. Versuchen Sie es in Ihrem catch-Block aufzurufen, um festzustellen, ob Sie tatsächlich die IOException erhalten.

+4

für eine solche Ausnahme gibt isConnected() true zurück, egal was passiert. Lesen Sie es als "Steckdose wurde irgendwann in der Vergangenheit verbunden" – kellogs

+3

Endgültige Absatz dieser Antwort ist völlig inkorrekt. isConnected() erkennt diese Bedingung nicht. – EJP

73

Was verursacht ein "gebrochenes Rohr" und, was noch wichtiger ist, ist es möglich, von diesem Zustand zu erholen?

Es wird durch etwas verursacht, das die Verbindung zum Schließen verursacht. (Es ist nicht Ihre Anwendung, die die Verbindung geschlossen hat: das hätte zu einer anderen Ausnahme geführt.)

Es ist nicht möglich, die Verbindung wiederherzustellen. Sie müssen eine neue öffnen.

Wenn es nicht wiederhergestellt werden kann, scheint dies ein gutes Zeichen dafür zu sein, dass ein irreversibles Problem aufgetreten ist und ich diese Socketverbindung einfach schließen sollte. Ist das eine vernünftige Annahme?

Ja. Sobald Sie diese Ausnahme erhalten haben, funktioniert der Socket nicht mehr. Es zu schließen ist das einzig Vernünftige.

Gibt es überhaupt eine Zeit, als diese IOException während der Socket-Verbindung noch richtig in erster Linie verbunden ist, wird auftreten würde (anstatt eine funktionierende Verbindung, die zu einem bestimmten Zeitpunkt nicht)?

No. (oder zumindest nicht ohne das richtige Verhalten des Stapels OS'es Netzwerk Grabung, die JVM und/oder Ihrer Anwendung.)


Ist es klug, immer anrufen SocketChannel.isConnected() bevor ein Versuch SocketChannel.write() ...

Im allgemeinen ist es eine schlechte Idee r.isXYZ() vor einigen Anruf zu nennen, die die (extern) Ressource verwendet r. Es gibt eine kleine Chance, dass der Status der Ressource zwischen die zwei Aufrufe ändert. Es ist eine bessere Idee, die Aktion auszuführen, die IOException (oder was auch immer) zu fangen, die sich aus der fehlgeschlagenen Aktion ergibt, und die erforderlichen Abhilfemaßnahmen ergreifen.

In diesem speziellen Fall ist der Aufruf isConnected() sinnlos. Die Methode ist so definiert, dass truezurückgegeben wird, wenn der Socket zu einem bestimmten Zeitpunkt in der Vergangenheit angeschlossen wurde. Sie erfahren nicht, ob die Verbindung noch aktiv ist. Die einzige Möglichkeit festzustellen, ob die Verbindung noch besteht, ist der Versuch, sie zu verwenden. z.B. Lese oder schreibe.

15

Defekte Pipe bedeutet, dass Sie an eine Verbindung geschrieben haben, die bereits am anderen Ende geschlossen ist.

isConnected() erkennt diese Bedingung nicht. Nur ein Schreiben tut es.

ist es ratsam, immer SocketChannel.isConnected() aufrufen, bevor Sie eine SocketChannel.write Versuch()

Es ist sinnlos. Die Buchse selbst ist verbunden. Du hast es verbunden. Was kann nicht verbunden sein, ist die Verbindung selbst, und Sie können nur feststellen, indem Sie es versuchen.