web-dev-qa-db-fra.com

java.net.SocketException: réinitialisation de la connexion

Je reçois l'erreur suivante en essayant de lire à partir d'un socket. Je fais une readInt() sur cette InputStream, et j'obtiens cette erreur. En parcourant la documentation, cela suggère que la partie cliente de la connexion a fermé la connexion. Dans ce scénario, je suis le serveur.

J'ai accès aux fichiers journaux du client et il ne ferme pas la connexion. En fait, ses fichiers journaux suggèrent que je ferme la connexion. Alors quelqu'un a-t-il une idée de la raison pour laquelle cela se produit? Quoi d'autre à vérifier? Cela se produit-il lorsque des ressources locales atteignent peut-être des seuils?


Je note que j'ai la ligne suivante:

socket.setSoTimeout(10000);

juste avant la readInt(). Il y a une raison à cela (longue histoire), mais, curieux de savoir, existe-t-il des circonstances dans lesquelles cela pourrait conduire à l'erreur indiquée? Le serveur tourne dans mon IDE, et j’ai laissé mon IDE bloqué sur un point d’arrêt, puis j’ai remarqué que les mêmes erreurs commençaient à apparaître exactement dans mes propres journaux dans mon IDE.

Quoi qu'il en soit, juste en le mentionnant, j'espère que ce ne sera pas un piège rouge. :-(

109
Darryl

Il y a plusieurs causes possibles.

  1. L'autre extrémité a délibérément réinitialisé la connexion, d'une manière que je ne documenterai pas ici. Ceci est rare et généralement incorrect pour un logiciel d'application, mais ce n'est pas inconnu pour un logiciel commercial.

  2. Plus généralement, cela est dû à l'écriture sur une connexion que l'autre extrémité s'est déjà fermée normalement. En d'autres termes, une erreur de protocole d'application.

  3. Cela peut également être causé par la fermeture d'un socket lorsqu'il y a des données non lues dans le tampon de réception du socket.

  4. Sous Windows, le terme "interruption de connexion causée par un logiciel", différent de "réinitialisation de la connexion", est dû à des problèmes de réseau liés à l'envoi de votre part. Il existe un article de la base de connaissances Microsoft à ce sujet.

105
user207421

La réinitialisation de la connexion signifie simplement qu'un TCP RST a été reçu. Cela se produit lorsque votre homologue reçoit des données qu’il ne peut pas traiter, et il peut y avoir plusieurs raisons à cela.

Le plus simple est de fermer le socket, puis d'écrire plus de données sur le flux de sortie. En fermant le socket, vous avez dit à votre pair que vous avez fini de parler et qu'il peut oublier votre connexion. De toute façon, quand vous envoyez plus de données sur ce flux, l’homologue le rejette avec un RST pour vous faire savoir qu’il n’écoute pas.

Dans d'autres cas, un pare-feu intermédiaire ou même l'hôte distant lui-même peut "oublier" votre connexion TCP. Cela peut arriver si vous n'envoyez pas de données pendant une longue période (2 heures est un délai d'expiration courant) ou si l'homologue a été redémarré et a perdu ses informations sur les connexions actives. L'envoi de données sur l'une de ces connexions obsolètes entraînera également un RST.


Mise à jour en réponse à des informations supplémentaires:

Examinez de près le comportement de la SocketTimeoutException. Cette exception est déclenchée si le délai d'attente configuré est dépassé alors qu'il est bloqué sur une opération de socket. L'état du socket lui-même n'est pas modifié lorsque cette exception est levée, mais si votre gestionnaire d'exceptions ferme le socket et tente ensuite d'y écrire, vous serez dans une condition de réinitialisation de la connexion. setSoTimeout() est destiné à vous donner un moyen propre de sortir d'une opération read() qui risquerait sinon de se bloquer indéfiniment, sans pour autant vous salir, telle que la fermeture du socket à partir d'un autre thread.

43
erickson

Chaque fois que j'ai des problèmes étranges comme celui-ci, je m'assois habituellement avec un outil tel que WireShark et je regarde les données brutes échangées. Vous pourriez être surpris de voir où des choses sont en train d'être déconnectées et que vous êtes seulement averti lorsque vous essayez de lire.

13
GEOCHET

C'est embarrassant de le dire, mais quand j'ai eu ce problème, c'était simplement une erreur de fermer la connexion avant de lire toutes les données. Dans les cas où de petites chaînes étaient renvoyées, cela fonctionnait, mais cela était probablement dû à l'intégralité de la réponse qui avait été mise en mémoire tampon, avant que je la ferme.

En cas de retour de longues quantités de texte, l'exception a été levée, puisqu'un tampon revenait.

Vous pouvez vérifier cet oubli. N'oubliez pas que l'ouverture d'une URL est comme un fichier, assurez-vous de la fermer (libérez la connexion) une fois qu'elle a été entièrement lue.

8
Scott S

Vous devriez inspecter la trace complète très soigneusement,

J'ai une application de socket serveur et corrigé un cas Java.net.SocketException: Connection reset.

Dans mon cas, cela se produit lors de la lecture d'un objet clientSocket Socket dont la connexion est fermée pour une raison quelconque. (Perte de réseau, blocage du pare-feu ou de l'application ou fermeture prévue)

En fait, je rétablissais la connexion quand une erreur s'est produite lors de la lecture de cet objet Socket.

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

La chose intéressante est for my Java Socket si un client se connecte à mon ServerSocket et ferme sa connexion sans rien envoyer is.read() s’appelle de manière récursive. socket vous essayez de lire à partir d'une connexion fermée. Si vous utilisez quelque chose comme ci-dessous pour l'opération de lecture;

while(true)
{
  Receive();
}

Ensuite, vous obtenez un stackTrace comme ci-dessous et ainsi de suite

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

Ce que j'ai fait est simplement de fermer ServerSocket, de renouveler ma connexion et d'attendre d'autres connexions clientes entrantes.

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


//...
}

Ceci rétablit ma connexion pour les losts de socket client inconnus

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...
            }
        }

Je ne pouvais pas trouver d'autre solution car, comme vous pouvez le voir ci-dessous, vous ne pouvez pas comprendre si une connexion est perdue sans un try and catch, car tout semble bien se passer. J'ai eu cet instantané pendant que j'obtenais Connection reset continuellement.

enter image description here

8
Davut Gürbüz

J'ai eu la même erreur. J'ai trouvé la solution au problème maintenant. Le problème était que le programme client se terminait avant que le serveur ne lise les flux.

5
kml_ckr

J'ai eu ce problème avec un système SOA écrit en Java. J'exécutais le client et le serveur sur différentes machines physiques et ils fonctionnaient bien pendant un long moment, puis ces réinitialisations de connexion désagréables apparaissaient dans le journal du client et il n'y avait rien d'étrange dans le journal du serveur. Redémarrer le client et le serveur n'a pas résolu le problème. Enfin, nous avons découvert que le tas côté serveur était plutôt plein. Nous avons donc augmenté la mémoire disponible pour la machine virtuelle Java: le problème a été résolu! Notez qu’il n’y avait pas d’erreur OutOfMemoryError dans le journal: la mémoire était simplement rare et non épuisée.

4
Pino

J'ai également eu ce problème avec un programme Java essayant d'envoyer une commande sur un serveur via SSH. Le problème était avec la machine exécutant le code Java. Il n'était pas autorisé à se connecter au serveur distant. La méthode write () se passait bien, mais la méthode read () lançait une Java.net.SocketException: Connection reset. J'ai résolu ce problème en ajoutant la clé SSH du client aux clés connues du serveur distant.

1
pmartin8

Vérifiez la version de votre serveur Java. Cela m'est arrivé parce que mon Weblogic 10.3.6 était sur JDK 1.7.0_75 qui était sur TLSv1. Le point de terminaison du repos que j'essayais de consommer fermait tout ce qui se trouvait en dessous de TLSv1.2.

Par défaut, Weblogic essayait de négocier le protocole partagé le plus puissant. Voir les détails ici: Problèmes avec la définition de la propriété système https.protocols pour les connexions HTTPS .

J'ai ajouté une journalisation SSL détaillée pour identifier le TLS pris en charge. Cela indiquait que TLSv1 était utilisé pour la poignée de main.
-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

J'ai résolu ce problème en transmettant la fonctionnalité à notre produit compatible JDK8, JDK8 par défaut étant TLSv1.2. Pour ceux limités à JDK7, j'ai également testé avec succès une solution de contournement pour Java 7 en mettant à niveau vers TLSv1.2. J'ai utilisé cette réponse: Comment activer TLS 1.2 dans Java 7

0
behold