157 votes

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

J'obtiens l'erreur suivante en essayant de lire à partir d'un socket. Je fais un readInt() sur ce point InputStream et j'obtiens cette erreur. En parcourant la documentation, cela suggère que la partie client 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, et en fait ses fichiers journaux suggèrent que je ferme la connexion. Quelqu'un a-t-il une idée de la raison pour laquelle cela se produit ? Que faut-il vérifier d'autre ? Cela se produit-il lorsque des ressources locales atteignent des seuils ?


Je note cependant que j'ai la ligne suivante :

socket.setSoTimeout(10000);

juste avant le readInt() . Il y a une raison à cela (longue histoire), mais par curiosité, y a-t-il des circonstances dans lesquelles cela pourrait conduire à l'erreur indiquée ? J'ai le serveur en cours d'exécution dans mon IDE, et il se trouve que j'ai laissé mon IDE bloqué sur un point d'arrêt, et j'ai alors remarqué que les mêmes erreurs exactement ont commencé à apparaître dans mes propres journaux dans mon IDE.

Quoi qu'il en soit, je ne fais que le mentionner, en espérant qu'il ne s'agisse pas d'un hareng rouge :-(.

131voto

EJP Points 113412

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. Il est rare, et généralement incorrect, que les logiciels d'application fassent cela, mais ce n'est pas inconnu pour les logiciels commerciaux.

  2. Plus souvent, il est causé par l'écriture sur une connexion que l'autre extrémité a déjà fermée normalement. En d'autres termes, il s'agit d'une erreur de protocole d'application.

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

  4. Sous Windows, l'"interruption de la connexion causée par le logiciel", qui est différente de la "réinitialisation de la connexion", est due à des problèmes de réseau provenant de votre côté. Il existe un article de la base de connaissances de Microsoft à ce sujet.

60voto

erickson Points 127945

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 dites à votre homologue que vous avez fini de parler, et qu'il peut oublier votre connexion. Lorsque vous envoyez quand même d'autres données sur ce flux, le pair les rejette avec un RST pour vous faire savoir qu'il n'écoute pas.

Dans d'autres cas, un pare-feu intermédiaire ou l'hôte distant lui-même peut "oublier" votre connexion TCP. Cela peut se produire si vous n'envoyez pas de données pendant une longue période (2 heures est un délai courant), ou parce que 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 défuntes provoquera également un RST.


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

Examinez attentivement votre façon de traiter les SocketTimeoutException . Cette exception est levée si le délai d'attente configuré est dépassé lors du blocage d'une opération de socket. L'état de la socket elle-même n'est pas modifié lorsque cette exception est levée, mais si votre gestionnaire d'exception ferme la socket, puis tente d'y écrire, vous serez dans une condition de réinitialisation de la connexion. setSoTimeout() est censé vous donner un moyen propre de sortir d'une read() qui pourrait autrement se bloquer indéfiniment, sans faire des choses sales comme fermer le socket depuis un autre thread.

20voto

GEOCHET Points 13787

Chaque fois que j'ai eu des problèmes bizarres comme celui-ci, je m'assois généralement avec un outil tel que WireShark et regardez les données brutes qui passent dans les deux sens. Vous pourriez être surpris de voir où les choses sont déconnectées, et où vous n'êtes que notifié à quand vous essayez de lire.

12voto

Davut Gürbüz Points 1609

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

J'ai une application de socket de serveur et j'ai fixé une java.net.SocketException: Connection reset cas.

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

En fait, j'étais en train de rétablir la connexion lorsque j'ai eu une erreur 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 !!!

Ce qui est intéressant, c'est que for my JAVA Socket si un client se connecte à mon ServerSocket et fermer sa connexion sans rien envoyer is.read() Il semble que le fait d'être dans une boucle infinie pour lire à partir de ce 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 une trace de pile 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, c'est fermer ServerSocket, renouveler ma connexion et attendre d'autres connexions de clients entrants.

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

//...
}

Cela rétablit ma connexion pour les pertes de socket de client inconnu.

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 n'ai pas trouvé d'autre moyen car, comme vous le voyez sur l'image ci-dessous, vous ne pouvez pas comprendre si la connexion est perdue ou non sans une try and catch parce que tout semble correct. J'ai eu ce cliché pendant que je prenais Connection reset en permanence.

enter image description here

10voto

Scott S Points 42

C'est embarrassant à dire, mais quand j'ai eu ce problème, c'était simplement une erreur de fermer la connexion avant d'avoir lu toutes les données. Dans les cas où de petites chaînes de caractères étaient renvoyées, cela fonctionnait, mais c'était probablement dû au fait que toute la réponse était mise en mémoire tampon, avant que je ne la ferme.

Dans les cas où de longues quantités de texte étaient renvoyées, l'exception était levée, car plus qu'un tampon était renvoyé.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X