Comment réparer java.net.SocketException: tuyau cassé?

J’utilise le client http apache commons pour appeler url en utilisant la méthode post pour poster les parameters et il lance rarement l’erreur ci-dessous.

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) 

Quelqu’un peut-il suggérer ce qui cause cette exception et comment le déboguer?

Cela est dû à l’écriture sur une connexion lorsque l’autre extrémité l’a déjà fermée.

Vous disposez donc d’un protocole d’application mal défini ou implémenté.

Dans notre cas, nous avons eu ce problème lors d’un test de charge sur notre serveur d’applications. Le problème a été que nous devions append de la mémoire supplémentaire à notre JVM car elle était en train de s’épuiser. Cela a résolu le problème.

Essayez d’augmenter la mémoire disponible pour la JVM ou surveillez l’utilisation de la mémoire lorsque vous obtenez ces erreurs.

Tous les stream et connexions ouverts doivent être correctement fermés. La prochaine fois que nous essaierons d’utiliser l’object urlConnection, cela ne provoquera pas d’erreur. Par exemple, le changement de code suivant a corrigé l’erreur pour moi.

Avant:

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

Après:

 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. 

SocketException: le canal interrompu est provoqué par «l’autre extrémité» (le client ou le serveur) qui ferme la connexion pendant que votre code lit ou écrit sur la connexion.

Il s’agit d’une exception très courante dans les applications client / serveur qui reçoivent du trafic provenant de clients ou de serveurs en dehors du contrôle de l’application. Par exemple, le client est un navigateur. Si le navigateur effectue un appel Ajax, et / ou si l’utilisateur ferme simplement la page ou le navigateur, cela peut tuer toute communication de manière inattendue. Fondamentalement, vous verrez cette erreur chaque fois que l’autre extrémité mettra fin à son application et que vous ne l’espériez pas.

Si vous rencontrez cette exception dans votre application, cela signifie que vous devez vérifier votre code à l’endroit où l’IO (Input / Output) se produit et l’envelopper avec un bloc try / catch pour intercepter cette exception IOException. C’est alors à vous de décider comment vous voulez gérer cette situation semi-valide.

Dans votre cas, l’appel le plus ancien est l’appel à HttpMethodDirector.executeWithRetryHttpMethodDirector.executeWithRetry -vous donc que l’appel est encapsulé dans le bloc try / catch et gérez-le comme bon vous semble.

Je déconseille fortement de consigner les erreurs spécifiques à SocketException-Broken Pipe en dehors des niveaux de débogage / trace. Sinon, cela peut être utilisé comme une forme d’attaque par déni de service DOS en remplissant les journaux. Essayez de durcir et de tester négativement votre application pour ce scénario commun.

J’ai implémenté la fonctionnalité de téléchargement de données via le serveur FTP et j’ai également trouvé la même exception lors de la reprise de ce téléchargement. Pour résoudre cette exception, vous devrez toujours vous déconnecter de la session précédente et créer une nouvelle instance du client et une nouvelle connexion avec le serveur. Cette même approche pourrait également être utile pour HTTPClient.

La cause est que le pair distant ferme son socket (crash par exemple), donc si vous essayez de lui écrire des données par exemple, vous obtiendrez ceci. pour résoudre cela, insérez des opérations de lecture / écriture sur socket entre:

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

Les réponses ci-dessus illustrent la raison de cette java.net.SocketException: Broken pipe : l’autre extrémité a fermé la connexion. J’aimerais partager l’expérience de ce qui s’est passé quand je l’ai rencontré:

  1. dans la demande d’un client, l’en Content-Type tête Content-Type est défini par erreur comme étant plus grand que le corps de la requête (en fait, il n’y avait aucun corps)
  2. le service du bas dans la prise tomcat attendait les données de ce corps de taille (http est sur TCP qui assure la livraison par encapsulation et …)
  3. à l’expiration de 60 secondes, tomcat Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception java.net.SocketTimeoutException: null une exception de Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception java.net.SocketTimeoutException: null : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception java.net.SocketTimeoutException: null
  4. Le client reçoit une réponse avec le code d’état 500 en raison de l’exception de délai d’attente.
  5. client close connection (car il reçoit une réponse).
  6. tomcat lance java.net.SocketException: Broken pipe car le client l’a fermée.

Parfois, tomcat ne lève pas d’exception de pip, car une exception de délai d’attente ferme la connexion, ce qui explique pourquoi une telle différence m’embrouille également.

JavaDoc:

La longueur maximale de la queue pour les indications de connexion entrantes (une demande de connexion) est définie sur 50. Si une indication de connexion arrive lorsque la queue est pleine, la connexion est refusée.

Vous devriez augmenter le paramètre “backlog” de votre ServerSocket, par exemple

 int backlogSize = 50 ; new ServerSocket(port, backlogSize); 

Le problème pourrait être que vos fichiers déployés ne sont pas mis à jour avec les méthodes RMI correctes. Vérifiez que votre interface RMI contient des parameters mis à jour ou des structures de données mises à jour que votre client ne possède pas. Ou que votre client RMI ne possède aucun paramètre différent de celui de votre version de serveur.

Ceci est juste une supposition éclairée. Après avoir redéployé les fichiers de classe de mon application serveur et procédé à un nouveau test, le problème du “tuyau cassé” a disparu.