Offizielle Gründe für "Software verursachte Verbindungsabbruch: Socket-Schreibfehler"

157

Angesichts dieses Stack-Trace-Snippets

Auslöser: java.net.SocketException: Software verursachte Verbindungsabbruch: Socket-Schreibfehler
 bei java.net.SocketOutputStream.socketWrite0 (native Methode)

Ich habe versucht, folgende Fragen zu beantworten:

  1. Welcher Code löst diese Ausnahme aus? (JVM? / Tomcat? / Mein Code?)
  2. Was bewirkt, dass diese Ausnahme ausgelöst wird?

Zu # 1:

Die JVM-Quelle von Sun enthält nicht genau diese Nachricht, aber ich denke, der Text, den die Software verursacht hat, hat den Verbindungsabbruch verursacht: Der Socket-Schreibfehler stammt von der nativen Implementierung von SocketOutputStream:

private native void socketWrite0(FileDescriptor fd, byte[] b, int off,
                 int len) throws IOException;

In Bezug auf # 2

Ich vermute, dass dies verursacht wird, wenn der Client die Verbindung beendet hat, bevor die vollständige Antwort erhalten wurde (z. B. eine Anfrage gesendet, aber bevor die vollständige Antwort erhalten wurde, wurde sie geschlossen / beendet / offline).

Fragen:

  1. Sind die obigen Annahmen korrekt (Nr. 1 und Nr. 2)?
  2. Kann dies von der Situation unterschieden werden: "konnte aufgrund eines Netzwerkfehlers auf der Serverseite nicht auf den Client schreiben "? oder würde das die gleiche Fehlermeldung darstellen?
  3. Und das Wichtigste: Gibt es ein offizielles Dokument (z. B. von Sun), in dem dies angegeben ist?

Ich brauche einen Beweis dafür, dass diese Stapelverfolgung der "Fehler" des Socket-Clients ist, und es gibt nichts, was der Server hätte tun können, um dies zu vermeiden. (außer das Abfangen der Ausnahme oder die Verwendung eines SocketOutputStream, der nicht von Sun JVM stammt, obwohl beide die Tatsache, dass der Client beendet wurde, nicht wirklich vermeiden)

Eran Medan
quelle
Ich habe dieses Problem beim Abbrechen eines Downloads mit Firefox
koppor
Hey Eran, ich bekomme diese Ausnahme auch beim Senden / Schreiben ( outs.write(audioBytes);) byte[]in OutputStream. Wenn Audio läuft und während der Wiedergabe, wenn der Benutzer auf ein anderes Menü klickt (das eine Serveranforderung sendet), wird auf der Konsole der gleiche Fehler angezeigt. Ist es also sicher, diese Ausnahme zu ignorieren?
Amogh
1
@ Amogh - Es scheint so, ja. Nach den Antworten ist dies im Grunde genommen ein Windows-spezifischer Fehler, aber ich gehe davon aus, dass Sie unter Linux dieselbe Ausnahme nur mit einem anderen Wortlaut erhalten ... (Mein Laien-Verständnis davon ist im Grunde, dass dies beim Senden verursacht wird über eine Steckdose an einen entfernten Ort X und X wurden in der Mitte getrennt, aber ich bin sicher, es ist nicht die genaueste Art, es zu beschreiben)
Eran Medan
1
Für mich geschah dies, als der Datenbankserver neu gestartet wurde und die Anwendung immer noch versuchte, über zuvor geöffnete Verbindungen abzufragen. Ich bin mir nicht sicher, warum diese nicht aktualisiert wurden, da wir DBCP-basiertes Pooling verwenden. Ein Neustart der Anwendung hat das Problem jedoch behoben.
Kshitiz Sharma

Antworten:

55

Dieser Fehler kann auftreten, wenn das lokale Netzwerksystem eine Verbindung abbricht, z. B. wenn WinSock eine hergestellte Verbindung schließt, nachdem die erneute Datenübertragung fehlgeschlagen ist (der Empfänger bestätigt niemals Daten, die über einen Datenstrom-Socket gesendet wurden).

Siehe diesen MSDN-Artikel . Siehe auch Einige Informationen zu "Software verursachte Verbindungsabbruch" .

Marquis von Lorne
quelle
3
@MatGessel Dieser Artikel wiederholt nur die Verwirrung und fügt einige seiner eigenen hinzu. WSAECONNABORTED ist ein Winsock-Fehlercode, daher kann es möglicherweise keine Berkeley-Erklärung dafür geben. Die beschriebene Situation bezüglich des HTTP-Servers würde ECONNRESET und nicht WSAECONNABORTED erzeugen.
Marquis von Lorne
@EJP, ich erhalte diese Ausnahme auch beim Senden / Schreiben von (outs.write (audioBytes);) Byte [] in OutputStream. Wenn Audio läuft und während der Wiedergabe, wenn der Benutzer auf ein anderes Menü klickt (das eine Serveranforderung sendet), wird auf der Konsole der gleiche Fehler angezeigt. Ist es also sicher, diese Ausnahme zu ignorieren?
Amogh
1
@rustyx Alle drei hier genannten Quellen geben an, dass es durch ACK-Fehler verursacht wird. Wenn Sie eine Quelle für Ihren eigenen Anspruch haben, zitieren Sie diese bitte.
Marquis von Lorne
2
Dies ist keine echte Antwort, da Sie keine Informationen erhalten, um das Problem weiter zu verfolgen. Die Antwort hier ist im Grunde "etwas Schlimmes ist im Netzwerk passiert". Es wäre sehr hilfreich zu verstehen, welche weiteren Protokolle und anderen Aktivitätsaufzeichnungen es mir ermöglichen könnten, das zugrunde liegende Problem genau zu bestimmen.
Derek Bennett
11

Das java.net.SocketExceptionwird ausgelöst, wenn beim Erstellen oder Zugreifen auf einen Socket (z. B. TCP ) ein Fehler auftritt . Dies kann normalerweise verursacht werden, wenn der Server die Verbindung beendet hat (ohne sie ordnungsgemäß zu schließen), bevor die vollständige Antwort angezeigt wird. In den meisten Fällen kann dies entweder durch das Timeout-Problem verursacht werden (z. B. die Antwort dauert zu lange oder der Server ist mit den Anforderungen überlastet), oder der Client hat die SYN gesendet, aber keine ACK empfangen (Bestätigung der Verbindungsbeendigung). . Bei Timeout-Problemen können Sie den Timeout-Wert erhöhen.

Die Socket-Ausnahme enthält normalerweise die angegebene Detailmeldung zu dem Problem.

Beispiel für detaillierte Nachrichten:

  • Software verursacht Verbindungsabbruch: Recv fehlgeschlagen.

    Der Fehler weist auf einen Versuch hin, die Nachricht zu senden, und die Verbindung wurde von Ihrem Server abgebrochen. Wenn dies beim Herstellen einer Verbindung zur Datenbank passiert ist, kann dies mit der Verwendung eines nicht kompatiblen Connector / J-JDBC-Treibers zusammenhängen .

    Mögliche Lösung: Stellen Sie sicher, dass Ihr CLASSPATH über die richtigen Bibliotheken / Treiber verfügt.

  • Software verursachte Verbindungsabbruch: Verbinden.

    Dies kann passieren, wenn beim Herstellen einer Verbindung zur Fernbedienung ein Problem auftritt. Zum Beispiel, weil der Virenprüfer die Remote-Mail-Anforderungen ablehnt .

    Mögliche Lösung: Überprüfen Sie den Virenscan-Dienst, ob er den Port für ausgehende Verbindungsanforderungen blockiert.

  • Software verursachte Verbindungsabbruch: Socket-Schreibfehler.

    Mögliche Lösung: Stellen Sie sicher, dass Sie die richtige Länge von Bytes in den Stream schreiben. Überprüfen Sie also genau, was Sie senden. Siehe diesen Thread .

  • Verbindung durch Peer zurückgesetzt: Socket-Schreibfehler / Verbindung durch Peer abgebrochen: Socket-Schreibfehler

    Die Anwendung hat nicht überprüft, ob auf der Serverseite eine Zeitüberschreitung für die Keep-Alive-Verbindung aufgetreten ist.

    Mögliche Lösung: Stellen Sie sicher, dass der HttpClient nicht null ist, bevor Sie aus der Verbindung lesen. E13222_01

  • Verbindung von Peer zurückgesetzt.

    Die Verbindung wurde vom Peer (Server) beendet.

  • Verbindung zurücksetzen.

    Die Verbindung wurde entweder vom Client beendet oder vom Serverende der Verbindung aufgrund einer Anforderung mit der Anforderung geschlossen.

    Siehe: Was verursacht meine java.net.SocketException: Verbindung zurückgesetzt?

Kenorb
quelle
Nur einer dieser 6 Punkte beantwortet die Frage tatsächlich falsch. Einige andere sind ebenfalls falsch. Die Anwendung kann nicht überprüfen, ob auf der Serverseite eine Zeitüberschreitung für die Keep-Alive-Verbindung aufgetreten ist. Das HttpClientWesen nullkann unmöglich a verursachen SocketException. Nicht die richtige Länge in den Stream zu schreiben, tut dies auch nicht.
Marquis von Lorne
9

Ich habe dies am häufigsten gesehen, wenn eine Unternehmensfirewall auf einer Workstation / einem Laptop im Weg steht und die Verbindung unterbrochen wird.

z.B. Ich habe einen Serverprozess und einen Clientprozess auf demselben Computer. Der Server überwacht alle Schnittstellen (0.0.0.0) und der Client versucht, eine Verbindung zur öffentlichen / privaten Schnittstelle herzustellen (beachten Sie nicht die Loopback-Schnittstelle 127.0.0.1).

Wenn das Netzwerk der Maschine getrennt ist (z. B. WLAN ausgeschaltet), wird die Verbindung hergestellt. Wenn der Computer mit dem Unternehmensnetzwerk verbunden ist (direkt oder VPN), wird die Verbindung hergestellt.

Wenn der Computer jedoch mit einem öffentlichen WLAN (oder Heimnetzwerk) verbunden ist, wird die Verbindung durch die Firewall unterbrochen. In dieser Situation funktioniert das Verbinden des Clients mit der Loopback-Schnittstelle einwandfrei, nur nicht mit der Home / Public-Schnittstelle.

Hoffe das hilft.

user2028913
quelle
3
Firewalls verhindern Verbindungen. Die Frage betrifft das Zurücksetzen einer vorhandenen Verbindung.
Marquis von Lorne
4

Um zu beweisen, welche Komponente ausfällt, würde ich die TCP / IP-Kommunikation mithilfe von Wireshark überwachen und prüfen , wer den Port tatsächlich schließt. Auch Zeitüberschreitungen könnten relevant sein.

Stapler
quelle
Niemand schließt den Hafen. Das Betriebssystem bricht die Verbindung ab.
Marquis von Lorne
@EJP Ich habe gesehen, dass dies passiert, wenn das überlastet wird und der Speicher ausgeht. Ich bin nicht sicher, ob es das Betriebssystem ist, das die Verbindung schließt, aber JVM wird wild.
Zee
1
@Zee Es gibt einen Unterschied zwischen dem Schließen eines Ports, der in Wireshark als FIN angezeigt wird, und dem Abbrechen der Verbindung, was nicht der Fall ist.
Marquis von Lorne
2

Haben Sie den Tomcat-Quellcode und die JVM-Quelle überprüft ? Das kann Ihnen mehr Hilfe geben.

Ich denke, Ihr allgemeines Denken ist gut. Ich würde ConnectExceptionin dem Szenario ein erwarten , dass Sie keine Verbindung herstellen konnten. Das Obige sieht sehr nach Client aus.

Brian Agnew
quelle
3
Ja, ich habe nachgesehen. Tomcats Quellen enthielten keine Permutation des Satzes, danke.
Eran Medan
1
Nein, er hat die Tomcat-Quelle UND die JVM-Quelle nicht überprüft .
Stephen C
Oder wenn er die JVM-Quelle überprüft hat, hat er nicht alles überprüft.
Stephen C
1
@Ehrann - Die Nachrichtenzeichenfolge befindet sich höchstwahrscheinlich in den nativen Quellen. Sie sollten aber auch das Ereignisprotokoll überprüfen. IMO, letzteres dürfte informativer sein.
Stephen C
6
Diese Nachrichtenzeichenfolge stammt tatsächlich vom Betriebssystem.
Marquis von Lorne
2

Für alle, die einfache Client Server-Programme verwenden und diesen Fehler erhalten, handelt es sich um ein Problem nicht geschlossener (oder zu früh geschlossener) Eingabe- oder Ausgabestreams.

PRO_gramista
quelle
2
Nein, ist es nicht. Dies würde ein Steckdosenleck darstellen, das schließlich zu einer FD-Erschöpfung führen würde.
Marquis von Lorne
0

Ich stand vor dem gleichen Problem.
Häufig tritt diese Art von Fehler auf, weil der Client seine Verbindung geschlossen hat und der Server immer noch versucht, auf diesen Client zu schreiben.
Stellen Sie also sicher, dass die Verbindung Ihres Clients geöffnet ist, bis der Server mit seinem Ausgabestream fertig ist.
Und noch etwas: Vergessen Sie nicht, den Eingabe- und Ausgabestream zu schließen.

Hoffe das hilft.
Und wenn Sie immer noch vor einem Problem stehen, informieren Sie Ihr Problem hier ausführlich.

Nirav Chhatrola
quelle
3
@ BhavinChhatrola Nein, eine falsche Antwort. Die beschriebene Situation führt zu einem "Zurücksetzen der Verbindung durch einen Peer", nicht zu dem Fehler in der Frage.
Marquis von Lorne
0

Dieser Fehler ist mir beim Testen meines Seifendienstes mit dem SoapUI-Client passiert. Im Grunde habe ich versucht, eine sehr große Nachricht (> 500 KB) zu erhalten, und SoapUI hat die Verbindung durch Timeout geschlossen.

Auf SoapUI gehen Sie zu:

Datei -> Einstellungen - Socket-Timeout (ms)

... und geben Sie einen großen Wert ein, z. B. 180000 (3 Minuten). Dies ist keine perfekte Lösung für Ihr Problem, da die Datei tatsächlich zu groß ist, aber zumindest eine Antwort erhalten.

Marco
quelle
0

Geschlossene Verbindung in einem anderen Client

In meinem Fall war der Fehler:

java.net.SocketException: Software caused connection abort: recv failed

Es wurde in Eclipse beim Debuggen einer Java-Anwendung empfangen, die auf eine H2-Datenbank zugreift. Die Fehlerquelle war, dass ich die Datenbank zunächst mit SQuirreL geöffnet hatte, um die Integrität manuell zu überprüfen. Ich habe das Flag verwendet, um mehrere Verbindungen zu derselben Datenbank zu aktivieren (dhAUTO_SERVER=TRUE ) , sodass es keine Probleme gab, über Java eine Verbindung zur Datenbank herzustellen.

Der Fehler trat auf, als ich nach einer Weile - es ist ein langer Java-Prozess - beschloss, SQuirreL zu schließen, um Ressourcen freizugeben. Es scheint, als ob SQuirreL die DB-Serverinstanz "besitzt" und mit der SQuirreL-Verbindung heruntergefahren wurde.

Beim Neustart der Java-Anwendung wurde der Fehler nicht erneut angezeigt.

config

  • Windows 7
  • Eclipse Kepler
  • SQuirreL 3.6
  • org.h2.Driver Version 1.4.192
manuelvigarcia
quelle
0

In meinem Fall habe ich die Client- und die Serverseite entwickelt, und ich habe die Ausnahme:

Ursache: Fehler beim Marshalling von Argumenten; verschachtelte Ausnahme ist: java.net.SocketException: Software verursachte Verbindungsabbruch: Socket-Schreibfehler

wenn Klassen in Client und Server unterschiedlich sind. Ich lade keine Serverklassen (Schnittstellen) auf den Client herunter, sondern füge dem Projekt dieselben Dateien hinzu. Aber der Weg muss genau der gleiche sein. Zum Beispiel habe ich auf dem Serverprojekt Java \ rmi \ services-Pakete mit einigen serviceInterface und Implementierungen. Ich muss dasselbe Paket auf dem Client-Projekt erstellen. Wenn ich es zum Beispiel durch java / rmi / server / services ändere, erhalte ich die obige Ausnahme. Dieselbe Ausnahme, wenn die Schnittstellenversion zwischen Client und Server unterschiedlich ist (auch wenn versehentlich eine leere Zeile hinzugefügt wurde ... Ich denke, rmi erstellt eine Art Hash von Klassen, um die Version zu überprüfen ... Ich weiß nicht ... Wenn es möglich wäre Hilfe ...

Elloco
quelle
-1

Mein Server hat diese Ausnahme im Pass 2 Tage ausgelöst und ich habe sie gelöst, indem ich die Trennfunktion verschoben habe mit:

outputStream.close();
inputStream.close();
Client.close();

Bis zum Ende des Listing-Threads. wenn es jemandem hilft.

Sefi Erlich
quelle
-1

In der unten erläuterten Situation wird die Clientseite eine solche Ausnahme auslösen:

Der Server wird aufgefordert, das Clientzertifikat zu authentifizieren. Der Client stellt jedoch ein Zertifikat bereit, dessen erweiterte Schlüsselverwendung die Clientauthentifizierung nicht unterstützt. Daher akzeptiert der Server das Clientzertifikat nicht und schließt dann die Verbindung.

Xiaoming
quelle
Diese Antwort ist falsch. In dem von Ihnen beschriebenen Fall wird eine SSLE-Ausnahme ausgelöst.
Präsident James K. Polk
Eigentlich wirft es SocketException genau wie die aktuelle Frage, die ich getestet hatte
Xiaoming
-1

SSL-Client-Seite wird eine solche Ausnahme in der folgenden Situation auslösen (ich hatte getestet) ,:

Der Server wird aufgefordert, das Clientzertifikat zu authentifizieren. Der Client stellt jedoch ein Zertifikat bereit, das die erweiterte Schlüsselverwendung nicht für die Clientauthentifizierung unterstützt.

Xiaoming
quelle
-3

Ich hatte das gleiche Problem mit wireMock, als ich die restlichen API-Aufrufe verspottete. Früher habe ich den Server folgendermaßen definiert:

WireMockServer wireMockServer = null;

Es sollte jedoch wie folgt definiert werden:

@Rule 
public WireMockRule wireMockRule = new WireMockRule(8089);
Yallaling Goudar
quelle
Das würde ein NullPointerException, nicht dieses Problem verursachen.
Marquis von Lorne