webentwicklung-frage-antwort-db.com.de

Wie behebt man Java.net.SocketException: Broken pipe?

Ich benutze Apache Commons http-Client zum Aufrufen der URL mit der Post-Methode, um die Parameter zu posten, und es wird selten der folgende Fehler ausgegeben.

Java.net.SocketException: Broken pipe
        at Java.net.SocketOutputStream.socketWrite0(Native Method)
        at Java.net.SocketOutputStream.socketWrite(SocketOutputStream.Java:92)
        at Java.net.SocketOutputStream.write(SocketOutputStream.Java:136)
        at Java.io.BufferedOutputStream.write(BufferedOutputStream.Java:105)
        at Java.io.FilterOutputStream.write(FilterOutputStream.Java:80)
        at org.Apache.commons.httpclient.methods.ByteArrayRequestEntity.writeRequest(ByteArrayRequestEntity.Java:90)
        at org.Apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.Java:499)
        at org.Apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.Java:2114)
        at org.Apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.Java:1096)
        at org.Apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.Java:398)

Kann jemand vorschlagen, was diese Ausnahme verursacht und wie sie behoben werden kann?

142
Mani

Dies wird verursacht durch:

  • in der Regel schreiben Sie an eine Verbindung, wenn das andere Ende sie bereits geschlossen hat.
  • seltener schließt der Peer die Verbindung, ohne alle Daten zu lesen, die bereits an seinem Ende anstehen.

In beiden Fällen haben Sie also ein schlecht definiertes oder implementiertes Anwendungsprotokoll.

Es gibt einen dritten Grund, den ich hier nicht dokumentieren werde, bei dem der Peer absichtlich zurücksetzt, anstatt die Verbindung ordnungsgemäß zu schließen.

74
user207421

In unserem Fall haben wir dies beim Ausführen eines Auslastungstests auf unserem App-Server festgestellt. Es stellte sich heraus, dass wir unserer JVM zusätzlichen Speicher hinzufügen müssen, da dieser zur Neige geht. Dies löste das Problem.

Erhöhen Sie den für die JVM verfügbaren Speicher, oder überwachen Sie die Speichernutzung, wenn diese Fehler auftreten.

29
Dave

SocketException: Eine unterbrochene Pipe wird dadurch verursacht, dass das "andere Ende" (der Client oder der Server) die Verbindung schließt, während Ihr Code entweder aus der Verbindung liest oder in die Verbindung schreibt.

Dies ist eine sehr häufige Ausnahme in Client/Server-Anwendungen, die Datenverkehr von Clients oder Servern außerhalb der Anwendungssteuerung empfangen. Der Client ist beispielsweise ein Browser. Wenn der Browser einen Ajax-Anruf tätigt und/oder der Benutzer die Seite oder den Browser einfach schließt, kann dies die gesamte Kommunikation unerwartet beenden. Grundsätzlich wird dieser Fehler immer dann angezeigt, wenn das andere Ende die Anwendung beendet und Sie nicht damit gerechnet haben.

Wenn diese Ausnahme in Ihrer Anwendung auftritt, sollten Sie den Code an der Stelle überprüfen, an der IO (Input/Output) auftritt, und ihn mit einem try/catch-Block umschließen, um diese IOException abzufangen Es liegt dann an Ihnen, zu entscheiden, wie Sie mit dieser vorübergehenden Situation umgehen möchten.

In Ihrem Fall ist der früheste Ort, an dem Sie noch die Kontrolle haben, der Anruf an HttpMethodDirector.executeWithRetry - Stellen Sie also sicher, dass der Aufruf mit dem try/catch-Block umschlossen ist, und behandeln Sie ihn so, wie Sie es für richtig halten.

Ich rate dringend davon ab, SocketException-Broken Pipe-spezifische Fehler auf einer anderen Ebene als der Debug-/Trace-Ebene zu protokollieren. Andernfalls kann dies als DOS-Angriff (Denial Of Service) verwendet werden, indem die Protokolle ausgefüllt werden. Versuchen Sie, Ihre Anwendung für dieses häufige Szenario zu verbessern und negativ zu testen.

7
AndyGee

Alle offenen Streams und Verbindungen müssen ordnungsgemäß geschlossen werden. Wenn Sie also das nächste Mal versuchen, das urlConnection-Objekt zu verwenden, wird kein Fehler ausgegeben. Zum Beispiel hat die folgende Codeänderung den Fehler für mich behoben.

Vor:

OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
bw.write("Some text");
bw.close();
out.close();

Nach:

OutputStream os = urlConnection.getOutputStream();
OutputStream out = new BufferedOutputStream(os);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
bw.write("Some text");
bw.close();
out.close();
os.close(); // This is a must.
4
Murali Mohan

Ich habe die Funktion zum Herunterladen von Daten über einen FTP-Server implementiert und auch dort die gleiche Ausnahme festgestellt, als ich den Download fortsetzte. Um diese Ausnahme zu beheben, müssen Sie immer die Verbindung zur vorherigen Sitzung trennen und eine neue Instanz des Clients sowie eine neue Verbindung zum Server erstellen. Dieser Ansatz könnte auch für HTTPClient hilfreich sein.

1
Naeem Ahmad

Die obigen Antworten veranschaulichen den Grund für dieses Java.net.SocketException: Broken pipe: Das andere Ende schloss die Verbindung. Ich möchte Erfahrungen teilen, was passiert ist, als ich darauf gestoßen bin:

  1. in einer Client-Anfrage wird der Header Content-Type fälschlicherweise größer gesetzt als der eigentliche Anfrage-Body (tatsächlich gab es überhaupt keinen Body).
  2. der unterste Dienst im Tomcat-Socket hat auf Body-Daten dieser Größe gewartet (http ist aktiviert TCP, wodurch die Lieferung durch Kapselung und ...)
  3. nach Ablauf von 60 Sekunden löst Tomcat eine Zeitüberschreitungs-Ausnahme aus: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception Java.net.SocketTimeoutException: null
  4. client erhält eine Antwort mit Statuscode 500 aufgrund der Zeitüberschreitungsausnahme.
  5. client-Verbindung schließen (weil es eine Antwort erhält).
  6. Tomcat wirft Java.net.SocketException: Broken pipe, Weil der Client es geschlossen hat.

Manchmal wirft Tomcat keine unterbrochene Pip-Ausnahme, da die Verbindung aufgrund einer Zeitüberschreitungsausnahme geschlossen wird. Warum verwirrt mich ein solcher Unterschied auch?.

0
Tiina

Das Problem könnte sein, dass Ihre bereitgestellten Dateien nicht mit den richtigen RMI-Methoden aktualisiert werden. Überprüfen Sie, ob Ihre RMI-Schnittstelle aktualisierte Parameter oder aktualisierte Datenstrukturen enthält, über die Ihr Client nicht verfügt. Oder dass Ihr RMI-Client keine Parameter hat, die sich von Ihrer Serverversion unterscheiden.

Dies ist nur eine fundierte Vermutung. Nach dem erneuten Bereitstellen der Klassendateien meiner Serveranwendung und dem erneuten Testen ist das Problem der unterbrochenen Pipe behoben.

0

Die Ursache ist, dass der Remote-Peer seinen Socket schließt (z. B. Absturz). Wenn Sie also beispielsweise versuchen, Daten in ihn zu schreiben, wird dies angezeigt. Um dies zu lösen, schützen Sie die Lese-/Schreibvorgänge für Sockets zwischen (versuchen Sie catch) und verwalten Sie dann den Verbindungsverlust in catch (Verbindung erneuern, Programm stoppen, ... usw.):

 try {
      /* your code */
 } catch (SocketException e) {
      e.printStackTrace();
      /* insert your failure processings here */
 }