java.net.SocketException: Verbindung zurückgesetzt

126

Beim Versuch, aus einem Socket zu lesen, wird der folgende Fehler angezeigt. Ich mache readInt()das InputStreamund bekomme diesen Fehler. In der Dokumentation wird darauf hingewiesen, dass der Client-Teil der Verbindung die Verbindung geschlossen hat. In diesem Szenario bin ich der Server.

Ich habe Zugriff auf die Client-Protokolldateien und die Verbindung wird nicht geschlossen. Die Protokolldateien deuten darauf hin, dass ich die Verbindung schließe. Hat jemand eine Idee, warum dies geschieht? Worauf sollte man noch achten? Tritt dies auf, wenn lokale Ressourcen möglicherweise Schwellenwerte erreichen?


Ich stelle fest, dass ich die folgende Zeile habe:

socket.setSoTimeout(10000);

kurz vor dem readInt(). Es gibt einen Grund dafür (lange Geschichte), aber nur merkwürdig, gibt es Umstände, unter denen dies zu dem angegebenen Fehler führen könnte? Ich habe den Server in meiner IDE ausgeführt, und meine IDE blieb zufällig an einem Haltepunkt hängen. Dann bemerkte ich, dass genau dieselben Fehler in meinen eigenen Protokollen in meiner IDE angezeigt wurden.

Wie auch immer, ich erwähne es nur, hoffentlich kein roter Hering. :-(

bläulich
quelle
Haben Sie Stapelspuren von beiden Seiten? Können Sie die Netzwerkarchitektur etwas genauer beschreiben? (Über das wilde Internet? Auf demselben Computer? Irgendwo dazwischen?) Passiert das die ganze Zeit? Oder zeitweise?
Stu Thompson

Antworten:

116

Es gibt mehrere mögliche Ursachen.

  1. Das andere Ende hat die Verbindung absichtlich zurückgesetzt, auf eine Weise, die ich hier nicht dokumentieren werde. Es ist selten und im Allgemeinen falsch, dass Anwendungssoftware dies tut, aber es ist für kommerzielle Software nicht unbekannt.

  2. Häufiger wird es durch das Schreiben in eine Verbindung verursacht, dass das andere Ende bereits normal geschlossen wurde. Mit anderen Worten, ein Anwendungsprotokollfehler.

  3. Dies kann auch durch Schließen eines Sockets verursacht werden, wenn sich ungelesene Daten im Socket-Empfangspuffer befinden.

  4. In Windows wird "Software verursacht Verbindungsabbruch", was nicht mit "Verbindungsrücksetzen" identisch ist, durch Netzwerkprobleme verursacht, die von Ihrem Ende gesendet werden. Es gibt einen Microsoft Knowledge Base-Artikel dazu.

Marquis von Lorne
quelle
@ MattLyons Danke. Es gibt viel bessere MSDN-Artikel. Ehrlich gesagt finde ich das schwer zu glauben. Eine Verbindung besteht erst, wenn die richtigen Quell- und Ziel-IP-Adressen hergestellt wurden. Die MSDN-Artikel, die ich gesehen habe, beziehen sich auf anhaltende Netzwerkfehler, die das Zeitlimit für die Verbindung überschreiten.
Marquis von Lorne
48

Das Zurücksetzen der Verbindung bedeutet einfach, dass ein TCP-RST empfangen wurde. Dies geschieht, wenn Ihr Peer Daten empfängt, die er nicht verarbeiten kann, und es kann verschiedene Gründe dafür geben.

Am einfachsten ist es, wenn Sie den Socket schließen und dann weitere Daten in den Ausgabestream schreiben. Durch Schließen des Sockets haben Sie Ihrem Kollegen mitgeteilt, dass Sie mit dem Sprechen fertig sind, und er kann Ihre Verbindung vergessen. Wenn Sie ohnehin mehr Daten in diesem Stream senden, lehnt der Peer diese mit einem RST ab, um Sie darüber zu informieren, dass er nicht zuhört.

In anderen Fällen kann eine dazwischenliegende Firewall oder sogar der Remote-Host selbst Ihre TCP-Verbindung "vergessen". Dies kann passieren, wenn Sie längere Zeit keine Daten senden (2 Stunden sind eine häufige Zeitüberschreitung) oder weil der Peer neu gestartet wurde und seine Informationen über aktive Verbindungen verloren hat. Das Senden von Daten über eine dieser nicht mehr funktionierenden Verbindungen führt ebenfalls zu einer RST.


Update als Antwort auf zusätzliche Informationen:

Schauen Sie sich Ihren Umgang mit dem genau an SocketTimeoutException. Diese Ausnahme wird ausgelöst, wenn das konfigurierte Zeitlimit überschritten wird, während ein Socket-Vorgang blockiert wird. Der Status des Sockets selbst wird nicht geändert, wenn diese Ausnahme ausgelöst wird. Wenn Ihr Ausnahmebehandler jedoch den Socket schließt und dann versucht, darauf zu schreiben, befindet sich die Verbindung zurück. setSoTimeout()soll Ihnen eine saubere Möglichkeit bieten, aus einem read()Vorgang auszubrechen, der andernfalls für immer blockieren könnte, ohne schmutzige Dinge wie das Schließen des Sockets von einem anderen Thread aus zu tun.

erickson
quelle
In mehrfacher Hinsicht nicht korrekt. Sowohl die Speicherbereinigung als auch das Beenden von Prozessen führen zu ordnungsgemäßen Abschlüssen und nicht zu Zurücksetzungen. Ein Schließen, gefolgt von einem Schreiben durch den Peer, kann jedoch eher zu einem Zurücksetzen als zu einer EOS führen. SocketTimeoutExceptions werden nur ausgelöst, wenn der Leser ein Lesezeitlimit festgelegt hat.
Marquis von Lorne
Und das bedeutet nicht immer, dass ein RST empfangen wurde. Es kann auch bedeuten, dass eine von dieser Seite generiert wurde.
Marquis von Lorne
17

Wenn ich solche seltsamen Probleme hatte, setze ich mich normalerweise mit einem Tool wie WireShark zusammen und schaue mir die Rohdaten an, die hin und her übertragen werden. Sie könnten überrascht sein, wo die Verbindung getrennt wird, und Sie werden nur benachrichtigt, wenn Sie versuchen, zu lesen.

GEOCHET
quelle
9

Es ist peinlich, es zu sagen, aber als ich dieses Problem hatte, war es einfach ein Fehler, dass ich die Verbindung geschlossen habe, bevor ich alle Daten gelesen habe. In Fällen, in denen kleine Zeichenfolgen zurückgegeben wurden, funktionierte dies, aber das lag wahrscheinlich daran, dass die gesamte Antwort gepuffert wurde, bevor ich sie schloss.

Bei längeren Textmengen wurde die Ausnahme ausgelöst, da mehr als ein Puffer zurückkam.

Sie könnten nach diesem Versehen suchen. Denken Sie daran, dass das Öffnen einer URL wie eine Datei ist. Schließen Sie sie unbedingt (lösen Sie die Verbindung), sobald sie vollständig gelesen wurde.

Scott S.
quelle
9

Sie sollten die gesamte Spur sehr sorgfältig prüfen.

Ich habe eine Server-Socket-Anwendung und einen java.net.SocketException: Connection resetFall behoben .

In meinem Fall geschieht dies beim Lesen von einem clientSocket- SocketObjekt, dessen Verbindung aus irgendeinem Grund geschlossen wird. (Netzwerk verloren, Firewall oder Anwendung stürzt ab oder soll geschlossen werden)

Eigentlich stellte ich die Verbindung wieder her, als beim Lesen von diesem Socket-Objekt ein Fehler auftrat.

Socket clientSocket = ServerSocket.accept();
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
int readed = is.read(); // WHERE ERROR STARTS !!!

Das Interessante ist, for my JAVA Socketwenn ein Client eine Verbindung zu my herstellt ServerSocketund seine Verbindung schließt, ohne dass sich irgendetwas is.read()rekursiv anruft. Es scheint, dass Sie versuchen, aus einer geschlossenen Verbindung zu lesen, weil Sie sich in einer Endlosschleife zum Lesen von diesem Socket befinden. Wenn Sie für den Lesevorgang etwas wie das Folgende verwenden;

while(true)
{
  Receive();
}

Dann bekommst du eine stackTrace wie unten weiter und weiter

java.net.SocketException: Socket is closed
    at java.net.ServerSocket.accept(ServerSocket.java:494)

Ich habe nur ServerSocket geschlossen, meine Verbindung erneuert und auf weitere eingehende Clientverbindungen gewartet

String Receive() throws Exception
{
try {                   
            int readed = is.read();
           ....
}catch(Exception e)
{
        tryReConnect();
        logit(); //etc
}


//...
}

Dadurch wird meine Verbindung für unbekannte Client-Socket-Verluste wiederhergestellt

private void tryReConnect()
        {
            try
            {
                ServerSocket.close();
                //empty my old lost connection and let it get by garbage col. immediately 
                clientSocket=null;
                System.gc();
                //Wait a new client Socket connection and address this to my local variable
                clientSocket= ServerSocket.accept(); // Waiting for another Connection
                System.out.println("Connection established...");
            }catch (Exception e) {
                String message="ReConnect not successful "+e.getMessage();
                logit();//etc...
            }
        }

Ich konnte keinen anderen Weg finden, weil Sie, wie Sie auf dem Bild unten sehen, nicht verstehen können, ob die Verbindung ohne a unterbrochen ist oder nicht try and catch, weil alles richtig zu sein scheint. Ich habe diesen Schnappschuss bekommen, während ich Connection resetununterbrochen war.

Geben Sie hier die Bildbeschreibung ein

Davut Gürbüz
quelle
6

Ich hatte den gleichen Fehler. Ich habe jetzt die Lösung für das Problem gefunden. Das Problem war, dass das Client-Programm beendet wurde, bevor der Server die Streams las.

kml_ckr
quelle
Das würde diese Ausnahme nicht alleine verursachen.
Marquis von Lorne
Dies würde der Fall sein, wenn System.exit (0) das Programm beendet und niemand socket.close () aufruft, da die Verbindung in einem schlechten Zustand ist und nicht ordnungsgemäß geschlossen wurde. Sooo richtiger gesagt, er hatte ein Client-Programm, das heruntergefahren wurde, ohne Sockets zu schließen;), was eine schlechte Sache ist und behoben werden sollte.
Dean Hiller
1
@ DeanHiller Nein, würde es nicht. Das Betriebssystem würde den Socket auf die gleiche Weise schließen, wie es die Anwendung haben sollte.
Marquis von Lorne
@EJP .... Ich bin nicht sicher ... Ich weiß nur, dass wir es mit System.exit reproduzieren können, aber ich erinnere mich nicht an das Betriebssystem / die Konfiguration, wie es vor einiger Zeit war .... Aufruf von socket.close ( ) auf dem Server verhinderte das Zurücksetzen der Verbindung und es verhielt sich besser.
Dean Hiller
2
@DeanHiller Der Lesevorgang wurde beendet , bevor der Schreibvorgang abgeschlossen war.
Marquis von Lorne
4

Ich hatte dieses Problem mit einem in Java geschriebenen SOA-System. Ich habe sowohl den Client als auch den Server auf verschiedenen physischen Computern ausgeführt und sie haben lange Zeit einwandfrei funktioniert. Dann wurden diese unangenehmen Verbindungsrücksetzungen im Clientprotokoll angezeigt und im Serverprotokoll war nichts Seltsames. Ein Neustart von Client und Server hat das Problem nicht gelöst. Schließlich stellten wir fest, dass der Heap auf der Serverseite ziemlich voll war, und erhöhten den für die JVM verfügbaren Speicher: Problem gelöst! Beachten Sie, dass das Protokoll keinen OutOfMemoryError enthielt: Der Speicher war nur knapp und nicht erschöpft.

Pino
quelle
2

Überprüfen Sie die Java-Version Ihres Servers. Ist mir passiert, weil mein Weblogic 10.3.6 auf JDK 1.7.0_75 war, das auf TLSv1 war. Der Restendpunkt, den ich verwenden wollte, war das Herunterfahren von Daten unter TLSv1.2.

Standardmäßig hat Weblogic versucht, das stärkste gemeinsame Protokoll auszuhandeln. Weitere Informationen finden Sie hier: Probleme beim Festlegen der https.protocols-Systemeigenschaft für HTTPS-Verbindungen .

Ich habe eine ausführliche SSL-Protokollierung hinzugefügt, um das unterstützte TLS zu identifizieren. Dies zeigte an, dass TLSv1 für den Handshake verwendet wurde.
-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

Ich habe dieses Problem behoben, indem ich die Funktion auf unser JDK8-kompatibles Produkt übertragen habe. JDK8 verwendet standardmäßig TLSv1.2. Für diejenigen, die auf JDK7 beschränkt sind, habe ich auch erfolgreich eine Problemumgehung für Java 7 getestet, indem ich auf TLSv1.2 aktualisiert habe. Ich habe diese Antwort verwendet: So aktivieren Sie TLS 1.2 in Java 7

Sumiya
quelle
Vielen Dank, Sie zeigen mir eine neue Richtung, um mein Problem zu beheben. und schließlich fand ich, dass es der Fall ist !!!
Karl Li
1

Ich hatte auch dieses Problem mit einem Java-Programm, das versuchte, einen Befehl über SSH auf einem Server zu senden. Das Problem war, dass der Computer den Java-Code ausführte. Es war nicht berechtigt, eine Verbindung zum Remote-Server herzustellen. Die write () -Methode war in Ordnung, aber die read () -Methode löste eine java.net.SocketException: Verbindungsrücksetzung aus. Ich habe dieses Problem behoben, indem ich den Client-SSH-Schlüssel zu den bekannten Schlüsseln des Remoteservers hinzugefügt habe.

pmartin8
quelle
0

Nach meiner Erfahrung stoße ich häufig auf folgende Situationen:

  1. Wenn Sie in einem Unternehmen arbeiten, wenden Sie sich an das Netzwerk- und Sicherheitsteam. Da bei Anfragen an externe Dienste möglicherweise eine Berechtigung für den entsprechenden Endpunkt erteilt werden muss .

  2. Ein weiteres Problem ist, dass das SSL-Zertifikat möglicherweise auf dem Server abgelaufen ist, auf dem Ihre Anwendung ausgeführt wird.

bmck
quelle