IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entrée/Sortie Java Discussion :

BufferedReader readLine() ne s'arrête jamais


Sujet :

Entrée/Sortie Java

  1. #1
    Membre confirmé

    Inscrit en
    Juin 2005
    Messages
    1 155
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 1 155
    Points : 475
    Points
    475
    Par défaut BufferedReader readLine() ne s'arrête jamais
    Hello les gens,
    Je fais face à un problème très ennuyeux, et je n'arrive pas à m'en dépêtrer.
    J'ai un client développé en java qui lit un flux en tcp émanant d'un serveur codé en vb6 il me semble (nous n'avons aucune spécs sur celui-ci)
    Nous avons mené des tests en interne (nous avons donc développé un programme serveur en java qui simule ce que devait réaliser le serveur vb6 cible) et bouzin marche.
    En essayant de tester avec le serveur cible on se retrouve face au problème suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    ...
    socket = new Socket(InetAddress.getByName(System
    					.getProperty(ConstantsC7CPIP.SYSTEM_C7CPIP_BVC_SERVER_IP)),
    					port/* , InetAddress.getByName("localhost"), port */);
    ...
    -> La connexion est bien établie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    ...
    //in est private static BufferedReader in;
    in = new BufferedReader(new InputStreamReader(
    					socket.getInputStream()));
    ...
    String message_distant = new String();
    logger.log(Level.INFO, "Le client est en attente de messages...");
    int operation = 0;
    while (/* operation == 0 && */operation != 99 && (message_distant = in.readLine()) != null) {
    //faire son boulot
    ...
    Avec le serveur en interne tout se passe bien (mais je me répète)
    Avec le serveur cible on n'arrive pas à sortir du in.readLine()
    Nous avons donc décidé d'essayer de lire en caractère par caractère:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    String chars = new String();
    int c;
    while ((c = in.read()) !=-1) {
    chars += (char) c;
    System.out.print((char) c);
    }
    System.out.println("message entier= " + chars);
    L'instruction System.out.print((char) c); affiche bien les caractères, cependant nous n'arrivons jamais à sortir de cette boucle j'en déduis que la condition relative au while ((c = in.read()) !=-1 n'est jamais vérifiée (perspicace) or les caractères du flux qui ont été affichés contiennent bien des retour chariot (CRLF)

    D’où peux provenir mon problème?
    Merci pour toutes vos contributions

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Les méthodes readLine()/read() retournent null/-1 uniquement lorsque le flux est fermé.


    a++

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 547
    Points : 21 602
    Points
    21 602
    Par défaut
    Un readLine() s'arrête soit quand il tombe sur une fin de ligne, soit quand il tombe sur la fin du stream. S'il ne s'arrête pas, c'est qu'aucune de ces situations n'arrive : ou bien il ne reçoit rien, ou bien ce qu'il reçoit n'est pas une fin de ligne.

    Je te suggère donc de douter que, comme tu le dis, vous recevez bien des CRLF quand vous lisez caractère par caractère. Ce n'est probablement pas le cas, ou alors le serveur envoie autre chose quand vous lisez caractère par caractère, que quand vous lisez par ligne (probablement d'autres différences dans le code que ce que tu montres.)

    Cela peut arriver aussi si vous avez un charset bizarre par défaut : les octets reçus seraient bien ceux d'un CRLF ASCII mais le reader, utilisant un charset incompatible ASCII, ne les reconnaîtrait pas.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Membre confirmé

    Inscrit en
    Juin 2005
    Messages
    1 155
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 1 155
    Points : 475
    Points
    475
    Par défaut
    @adiGuba
    Merci pour ta réponse.
    Salut,


    Les méthodes readLine()/read() retournent null/-1 uniquement lorsque le flux est fermé.


    a++
    heu... non?
    String java.io.BufferedReader.readLine() throws IOException


    Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.

    Renvois :
    A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
    Emissions :
    IOException - If an I/O error occurs

    int java.io.BufferedReader.read() throws IOException


    Reads a single character.

    Remplace : read() dans Reader
    Renvois :
    The character read, as an integer in the range 0 to 65535 (0x00-0xffff), or -1 if the end of the stream has been reached
    Emissions :
    IOException - If an I/O error occurs
    @thelvin
    Merci pour ta réponse. Je penche pour l'histoire du charset incompatible. Demander à ce que l'envoi soit en binaire ? Quel puis-je y faire sinon ?

    Edit: j'ai trouvé ça:
    InputStream in = System.in;
    Charset charset = Charset.forName("UTF-8");
    InputStreamReader reader = new InputStreamReader(in, charset);
    Comment savoir quel charset ils utilisent ? (Ils ne savent pas)
    Avec leurs données lues copiées collées sur notepad++ j'ai Dos/Windows ANSI, le même format que nous utilisions pour nos tests en internes.

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par jadey Voir le message
    heu... non?
    C'est pourtant ce qui est indiqué dans le texte que tu as posté :
    A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
    Si tu attends un null (ou un -1 via read()), tu ne l'obtiendras que lorsque la socket sera fermé.


    a++

  6. #6
    Membre confirmé

    Inscrit en
    Juin 2005
    Messages
    1 155
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 1 155
    Points : 475
    Points
    475
    Par défaut
    @adiGuba
    Ce n'est pas ce que je comprends en lisant la javadoc précitée.
    Je suis d'accord que en ce qui concerne readLine(), null n'est renvoyée qu'a la fin du stream.
    Cependant :
    Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.
    Suggère que la méthode sert aussi à renvoyer une ligne sans pour autant que le flux soit terminé si en rencontre LF, CR ou encore CRLF.
    Dans mes tests en interne j'ai le souvenir d'avoir fait sur la partie serveur des:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    out.println("message1");
    out.flush();
    Thread.sleep(5000);
    out.println("message2");
    out.flush();
    Thread.sleep(5000);
    ...
    et les messages parvenaient et étaient traités à interval de 5 secondes.

  7. #7
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par jadey Voir le message
    Je suis d'accord que en ce qui concerne readLine(), null n'est renvoyée qu'a la fin du stream.
    C'est tout ce que j'ai dit : null est renvoyé lorsque le flux est fermé !

    Dans ton premier message, tu semblais t'étonner de ne pas sortir de la boucle et de ne pas recevoir de -1, mais c'est normal tant que le flux n'est pas fermé.



    Perso je m'orienterais plus vers le protocole de discussion que tu as mis en place.
    Comment fonctionne la discussion ? Qu'est-ce qui est envoyé par ton serveur ? Comment ?

    Attention également à bien flusher les données, sinon il est possible qu'elles ne soient pas réellement envoyé...


    a++

  8. #8
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 547
    Points : 21 602
    Points
    21 602
    Par défaut
    Je précise que ce que j'ai dit, c'est en comprenant que ce n'est pas de la boucle, qu'on arrive pas à sortir, mais d'un seul appel à BufferedReader.readLine().
    Si je me suis trompé là-dessus, alors il faut oublier tout ce que j'ai dit.

    Citation Envoyé par jadey Voir le message
    Merci pour ta réponse. Je penche pour l'histoire du charset incompatible.
    Pas moi. J'ai jamais rencontré de plate-forme utilisant par défaut un charset incompatible. Ça peut se construire mais j'y crois pas trop.

    Citation Envoyé par jadey Voir le message
    Demander à ce que l'envoi soit en binaire ?
    What ? C'est de l'informatique, tout est sous forme binaire. Si tu veux lire les octets et pas le texte, tu as qu'à le faire, en utilisant un BufferedInputStream au lieu d'un BufferedReader.

    Mais en principe ça ne devrait pas être nécessaire. La situation que tu nous décris n'existe pas dans le monde réel. Si tu as vraiment des CRLF dans le flux, et que le BufferedinputStream n'utilise pas un charset bizarre, alors il va voir les fins de lignes et renvoyer la ligne. Si tu observes autres chose c'est que tu t'es trompé quelque part, par exemple le code que tu crois tester n'est pas vraiment le code que tu testes. Ou alors le serveur n'envoie pas vraiment la même chose dans les deux cas, parce que tu utilises pas le même ou quelque chose de ce genre.

    Citation Envoyé par jadey Voir le message
    Comment savoir quel charset ils utilisent ? (Ils ne savent pas)
    Sans importance pour l'instant, du moment qu'il est ASCII-compatible. Ascii ou latin-1 ou utf-8 ou windows-1252, n'importe quoi mais quelque chose.
    Si ça change quelque chose ça veut dire que tu avais vraiment un charset par défaut bizarre genre utf-16, et à ce moment-là ton problème sera résolu et il sera toujours temps de te demander comment lire les accents.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #9
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Je précise que ce que j'ai dit, c'est en comprenant que ce n'est pas de la boucle, qu'on arrive pas à sortir, mais d'un seul appel à BufferedReader.readLine().
    Oui le problème n'est pas clair. Perso je ne l'ai pas compris comme cela en tout cas.

    Toutefois si readLine() ne renvoi rien cela peut également être un problème de cache si le serveur ne force pas le flush explicitement.


    a++

  10. #10
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 547
    Points : 21 602
    Points
    21 602
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Toutefois si readLine() ne renvoi rien cela peut également être un problème de cache si le serveur ne force pas le flush explicitement.
    Oui mais on aurait le même problème à un moment ou à un autre en lisant caractère par caractère ou octet par octet.
    De manière générale, il se trompe certainement en disant que le problème n'apparaît pas en lisant par caractère alors qu'il apparaît en lisant par ligne.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  11. #11
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Est-il possible que ce soit un problème de buffer? readLine ne lit pas caractère par caractère, mais lit des blocs de la taille de son buffer. Probablement que le StreamDecoder derrière le buffer veuille lire le maximum possible et qu'à son tour, le socket veuille retourner le maximum possible et ne pas se contenter du dernier paquet TCP/IP.


    Du coup un appel à socket.setSOTimeout(200) par exemple pourrait résoudre le problème.

  12. #12
    Membre confirmé

    Inscrit en
    Juin 2005
    Messages
    1 155
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 1 155
    Points : 475
    Points
    475
    Par défaut
    J'ai réussi à contourner le problème en réalisant une lecture en caractère par caractère, seulement je constate que la méthode .read() à une fâcheuse tendance à voir des caractères LF et CR partout, du coup je suis obligé de faire un test par rapport à l'ascii du caractère lu et de ne concaténer que si différent de 10 (LF) et différent de 13 (CR) Je ne sais pas si c'est la bonne manière de faire mais ça à l'air de marcher correctement.
    Sinon, si vous regardez le premier code soumis, la condition d'entrée dans le while porte sur le retour de null par .readLine()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    while (/* operation == 0 && */operation != 99 && (message_distant = in.readLine()) != null ) {
    ...
    Cela n'était pas le cas initialement la lecture se faisant à l'entrée dans la boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int operation =0;
    while (/* operation == 0 && */operation != 99) {
    message_distant = in.readLine();
    ...
    Nous avons réalisé cette modif. lorsque nous avons constaté que nous n'arrivions pas à lire le flux reçu, il est probable qu'a ce moment le serveur cible n'envoyait effectivement encore rien du tout. Pour l'instant j'ai trop la trouille de changer pour revenir à readLine() du moins le temps de stabiliser d'autre problèmes. J'espère que cela est plus clair maintenant.

  13. #13
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    pas vraiment. read n'a pas la 'facheuse tendance' de voir des CR et LF partout. Il vois exactement ce que ton serveur lui envoie. Si le serveur envoie du caca, tu reçois du caca.

Discussions similaires

  1. [SSIS][SSMS][2k5] Le job ne s'arrête jamais
    Par clementratel dans le forum SSIS
    Réponses: 0
    Dernier message: 02/12/2008, 17h11
  2. le package ne s'arrête jamais ?
    Par Mathusalem dans le forum SSIS
    Réponses: 2
    Dernier message: 22/08/2008, 12h10
  3. [DOM] AJAX: le chargement de la page ne s'arrête jamais
    Par Amallric dans le forum Général JavaScript
    Réponses: 18
    Dernier message: 20/07/2008, 12h05
  4. ventilos ne s'arrête jamais de tourner
    Par sweety107 dans le forum Composants
    Réponses: 9
    Dernier message: 02/09/2005, 17h27
  5. BufferedReader + ReadLine()
    Par mimil dans le forum Entrée/Sortie
    Réponses: 5
    Dernier message: 21/05/2005, 21h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo