OutputStream.write () réussi mais les données ne sont pas livrées

J'ai un comportement très étrange pendant l'écriture sur un socket. Dans mon client mobile, j'utilise un socket initialisé comme suit:

private void initSocket() { socket = new Socket(); socket.connect(new InetSocketAddress(host, port)); os = new DataOutputStream(socket.getOutputStream()); is = new DataInputStream(socket.getInputStream()); } 

Puis, périodiquement (toutes les 60 secondes), je lis et j'écris des données sur cette prise (le code ici est un peu simplifié):

  • Disposition Android: remplissez le reste de l'espace sauf
  • Ne pas afficher la superposition avec le tiroir de navigation Android
  • Dois-je utiliser _ID comme une clé primaire SQlite? Et doit-il être un INT? (Android Dev)
  • Les images WebView ne s'affichent pas avec HTTPS
  • Comment injectez-vous une configuration spécifique à la création dans un APK?
  • Comment définir par programme l'attribut layout_align_parent_right d'un bouton dans la mise en page relative?
  •  if(!isSocketInitialized()) { initSocket(); } byte[] msg = getMessage(); os.write(msg); os.flush(); int bytesAvailable = is.available( ); if(bytesAvailable>0) { byte[] inputBuffer = new byte[bytesAvailable]; int numRead = is.read(inputBuffer, 0, bytesAvailable); processServerReply(inputBuffer, numRead); } 

    Et il fonctionne. Mais … Parfois (très rarement, peut-être 1 ou 2 fois par jour) mon serveur ne reçoit pas de données. Le journal de mes clients ressemble à:

     Written A Written B Written C Written D Written E 

    etc. Mais du côté du serveur, il ressemble à:

     Received A Received E 

    Les enregistrements de données B, C, D n'ont pas été reçus, en dépit du fait que du côté du client, il semble que toutes les données ont été envoyées sans aucune exception!

    De telles lacunes peuvent être petites (2-3 minutes), ce qui n'est pas très grave, mais parfois elles peuvent être très grandes (1-2 heures = 60-120 cycles) et c'est vraiment un problème pour mes clients.

    Je n'ai vraiment aucune idée de ce qui peut être faux. Les données semblent être envoyées par le client, mais elles n'arrivent jamais du côté du serveur. Je l'ai également vérifié avec un proxy.

    J'ai seulement des journaux et je ne peux pas reproduire ce problème (mais cela arrive à mon client plus d'une fois tous les jours) et dans les journaux, parfois, je vois que la connexion est cassée avec une exception "sendto failed: ECONNRESET (Réinitialisation de la connexion par pair ) ". Après cela, le programme ferme le socket, le réinitialise:

     // close is.close(); os.close(); socket.close(); // reinitialize initSocket(); 

    Et essaie d'écrire les données comme décrit ci-dessus. Ensuite, je vois le problème: connexion établie, écriture réussie, mais NON DATA est arrivé sur le serveur!

    Peut-être qu'il a quelque chose à voir avec ECONNRESET peut-être pas, mais je veux mentionner cela parce que c'est peut-être important.

    Je serais très reconnaissant pour vos idées et conseils.

    PS Peut-être qu'il joue un rôle: le code client s'exécute sur un appareil mobile Android qui se déplace (c'est dans une voiture). La connexion Internet est établie via GPRS.


    UPD: je peux le reproduire! Au moins partiellement (le client envoie A, B, C, D, E et le serveur reçoit seulement A). Il se produit chaque fois si:

    1. La connexion est établie, le client lit et écrit -> OK

    2. La connexion est perdue (j'arrête mon routeur WLAN :)), je suis devenu IOException, je ferme les flux et le socket -> OK

    3. J'ouvre mon routeur, la connexion est de retour, j'initialise le socket à nouveau, le programme exécute write () sans exception, mais … aucune donnée arrive au serveur.

    BTW puisque la connexion est à nouveau disponible () renvoie toujours 0.

    2 Solutions collect form web for “OutputStream.write () réussi mais les données ne sont pas livrées”

    Débarrassez-vous du test available() . Si le pair doit répondre, lisez-le. Sinon, parfois, vous lisez la réponse et parfois vous ne le feriez pas, et vous serez désactivé. Il existe très peu d'utilisations correctes available() , et ce n'est pas l'une d'entre elles.

    La cause de ce comportement étrange était une prise non fermée du côté du serveur. Je pourrais le reproduire avec un petit client et un serveur. Les deux se composent de quelques lignes de code, qui font les éléments suivants:

    1. Se connecter au serveur
    2. Simuler un point mort (par exemple, éteignez votre WiFi)
    3. Fermez la prise côté client
    4. NE PAS FERMER la prise côté serveur
    5. Allumez votre WiFi
    6. Établir une nouvelle connexion à partir du client
    7. Écrire des données sur cette connexion

    Voila! Le client écrit des données sans aucune erreur, mais le serveur ne le reçoit pas …

    Mais si le serveur ferme le socket aussi, le serveur peut lire ces données. Donc, la solution devrait être de fermer le socket après un délai d'attente du côté du serveur.

    Malheureusement, dans mon cas, ce n'est pas viable, car le serveur est un logiciel tiers exclusif.

    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.