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 :

Comment bloquer un appele read() sur une socket ?


Sujet :

Entrée/Sortie Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 70
    Par défaut Comment bloquer un appele read() sur une socket ?
    Bonjour,

    Je fais transiter des bytes par le réseau, et la difficulté que j'ai c'est de réussir à bloquer les appels read() .


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    		ServerSocket socket = new ServerSocket(12345);	
    		Socket clientSocket;		
    		try
    		{
    			clientSocket = socket.accept();
    			System.out.println("Un nouveau client");
     
    			InputStream in2 = clientSocket.getInputStream();
     
    			byte fixedByte, id, size;
     
    			while(true)
    			{
    				System.out.println("reception du message");
    				fixedByte = (byte) in2.read();
    				id = (byte) in2.read();
    				size = (byte) in2.read();
    				System.out.println(size);
     
    				ByteBuffer buf = ByteBuffer.allocate(size+3);
    				byte[] b = new byte[size];
     
    				buf.put(fixedByte);
    				buf.put(id);
    				buf.put(size);
     
    				in2.read(b);
    				buf.put(b);
     
    				buf.rewind();
     
    				System.out.println(buf);
    			}			
    		}
    		catch (Exception e)	
                    {
    			e.printStackTrace();
    		}
    	}

    L'affichage

    serveur
    Un nouveau client

    // iteration 1
    reception du message
    52
    // le buffer est rempli avec la taille exacte
    java.nio.HeapByteBuffer[pos=0 lim=55 cap=55]

    // iteration 2
    reception du message
    // le read() retourn -1
    -1
    // exception lors ByteBuffer.allocate(size)
    java.lang.NegativeArraySizeException
    at MainServer.main(MainServer.java:96)

    Lors de la 1er itération , les données sont bien récupérés.

    Cependant, lors de la 2eme itération, le read() retourn -1,
    je ne souhaite pas faire d'attente actives.


    Comment je peux m'en sortir?


    Merci d'avance.

  2. #2
    Membre Expert
    Avatar de yotta
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Septembre 2006
    Messages
    1 095
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 095
    Par défaut Peut être une piste...
    Bonjour,

    Comme un byte est type primaire java qui représente un octet signé sur 8 bits, ce dernier peut représenter des valeurs comprises entre -128 et +127. Le fait de réceptionné -1 en guise de taille ne signifierait-il pas tout simplement que la taille annoncée est de 128 ?
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 70
    Par défaut
    Bonjour,

    même en envoyant rien du tout par le client, in2.read() retourne -1

    pursang, c'est exacte pour les bytes
    cependant, lorsque vous parlez de tailles annoncés, je ne voie pas à quoi vous faites référence.


    Par ailleurs j'ai essayé d'utiliser ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    InputStream is = socket.getInputStream();
    ObjectInputStream bufferIN = new ObjectInputStream (is);
     
     
    // puis après dans le while, à la place des in2.read()
    // 1)
    size = (byte) bufferIN.readByte();
     
    // OU 
    // 2)
    size = (byte) bufferIN.read();
    j'ai ce message :

    1)
    // Lorsque j'envoie des données
    serveur
    Un nouveau client
    reception du message
    java.io.StreamCorruptedException: invalid type code: FF
    at java.io.ObjectInputStream$BlockDataInputStream.readBlockHeader(ObjectInputStream.java:2480)
    at java.io.ObjectInputStream$BlockDataInputStream.refill(ObjectInputStream.java:2515)
    at java.io.ObjectInputStream$BlockDataInputStream.read(ObjectInputStream.java:2587)
    at java.io.ObjectInputStream.read(ObjectInputStream.java:837)
    at MainServer.main(MainServer.java:85)


    // Lorsque je n'envoie rien
    serveur
    Un nouveau client
    reception du message
    taille = -1
    -1
    java.lang.NegativeArraySizeException
    at MainServer.main(MainServer.java:98)

    2)
    // Lorsque j'envoie des données
    serveur
    Un nouveau client
    reception du message
    java.io.StreamCorruptedException: invalid type code: FF
    at java.io.ObjectInputStream$BlockDataInputStream.readBlockHeader(ObjectInputStream.java:2480)
    at java.io.ObjectInputStream$BlockDataInputStream.refill(ObjectInputStream.java:2515)
    at java.io.ObjectInputStream$BlockDataInputStream.read(ObjectInputStream.java:2587)
    at java.io.ObjectInputStream$BlockDataInputStream.readByte(ObjectInputStream.java:2736)
    at java.io.ObjectInputStream.readByte(ObjectInputStream.java:912)
    at MainServer.main(MainServer.java:85)


    // lorsque je n'envoie rien
    serveur
    Un nouveau client
    reception du message
    java.io.EOFException
    at java.io.ObjectInputStream$BlockDataInputStream.readByte(ObjectInputStream.java:2738)
    at java.io.ObjectInputStream.readByte(ObjectInputStream.java:912)
    at MainServer.main(MainServer.java:85

  4. #4
    Membre Expert
    Avatar de yotta
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Septembre 2006
    Messages
    1 095
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 095
    Par défaut Pardonnez-moi c'était une fausse piste.
    Bonjour,

    En fait, je viens de remarquer que vous ne contrôler pas l'état de votre flux. Et d'après la documentation de l'API java, la méthode read de InputStream renvoie le byte lu, ou -1 si la fin du flux est atteinte.
    Bref, lorsque votre méthode read renvoie -1, c'est qu'il n'y a plus de données à recevoir.
    En générale, on fait un Thread dédié au dialogue. Histoire de remettre le socketserver immédiatement en écoute.
    Dans le Thread a qui on aura pris soin de fournie le socket client, on fait un while conditionné sur la validité des données du flux => while (flux.available()>0)
    Le plus simple est de bufferiser le dialogue. On crée un byte[1024] de longueur fictive sans se préoccuper du nombre d'octets disponible sur le flux, et on invoque la méthode read(byte[] b). Si les données envoyées représente moins de 1024 octets (taille de notre buffer), ce dernier sera tout simplement comblé de 0 je crois. Le fait de ne plus présenter de données après le read fait sortir le programme de la boucle. Si au contraire les données représentent plus de 1024 octets, notre tableau d'octets sera tout simplement rempli, on boucle, et on poursuit la lecture. Entre temps, celon la nature des données, soit on stock dans un Vector ou autre, soit on concatène dans une chaîne.
    Je vous donne un exemple : Je pars du principe que les données sont du texte.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
     
     
    Le client :
    public class client {
     
        public static void main(String args[]) {
            try {
                Socket clientSocket = new Socket("localhost", 3456);
                BufferedOutputStream ecrivain = new BufferedOutputStream(clientSocket.getOutputStream());
                String chaineTest = new String("Coucou et encore coucou...1234567890");
                ecrivain.write(chaineTest.getBytes());
                ecrivain.flush();
                ecrivain.close();
                }
            catch (Exception e) {
                e.printStackTrace();
                }
            }
    }
     
    Le serveur :
     
    public class serveur {
     
        private static Dialogue dialogue = null;
     
        public static void main(String args[]) {
            try {
                ServerSocket serveur = new ServerSocket(3456);
                while (true) {
                    System.out.println("Message de serveur : \"Serveur à l'écoute...\"");
                    dialogue = new Dialogue(serveur.accept());
                    Thread t = new Thread(dialogue);
                    t.start();
                    System.out.println("Message de serveur : \"Nouveau dialogue pris en charge.\"");
                    }
                }
            catch (Exception e) {}
            }
    }
     
    Le Thread de dialogue :
     
    public class Dialogue implements Runnable {
     
        private Socket client = null;
     
        public Dialogue(Socket client) {
            if (client != null) this.client = client;
            }
     
        public void run() {
            if (client != null) {
                try {
                    BufferedInputStream fluxIn = new BufferedInputStream(client.getInputStream());
                    String chaine = new String();
                    byte[] lecteur = new byte[1024];
                    while (fluxIn.available() == 0) Thread.sleep(100);
                    while (fluxIn.available() > 0) {
                        fluxIn.read(lecteur);
                        chaine += new String(lecteur);
                        }
                    chaine = chaine.substring(0, chaine.indexOf(String.valueOf((char) 0)));
                    System.out.println("Message de client : \"Message recu :\n" + chaine + "\"");
                    }
                catch (Exception e) {}
                }
            }
    }
    J'ai écrit et testé ce code, il est fonctionnel et m'affiche bien les messages reçus tout en poursuivant l'écoute.
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 70
    Par défaut
    Bonjour pursang

    Je comprends ce que vous avez écris,
    seulement il y a deux choses qui me dérangent.

    D'une part, pour attendre un message, je ne souhaite pas faire un while.
    En C lorsque la file des messages est vide, le processus est endormi, puis réveillé lors de la réception d'un message.

    Un extrait du man de recvfrom() en C.
    Si aucun message n'est disponible sur la socket, les fonctions de
    réception se mettent en attente, à moins que la socket soit non blo‐
    quante (voir fcntl(2)) auquel cas la valeur -1 est renvoyée, et errno
    est positionnée à EAGAIN ou EWOULDBLOCK. Les fonctions de réception
    renvoient normalement les données disponibles sans attendre d'avoir
    reçu le nombre exact réclamé.
    Et idem pour le read() et autres fonctions lisant les sockets.

    Je cherche donc une fonction de lecture bloquante en java.
    Cependant, si cela n'existe pas, je ferais un while suivit d'un sleep.


    L'autre point, c'est la création d'un objet 'Dialogue' à chaque requête du même client.
    Mais cela peut être contourner par un while englobant les fonctions de lecture.


    En fin de compte ce que je cherche c'est juste un fonction de lecture (de bytes) de socket non bloquante, si cela existe en java.

  6. #6
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par maryooman Voir le message
    En C lorsque la file des messages est vide, le processus est endormi, puis réveillé lors de la réception d'un message.
    Oui... Comme dans tous les langages de ce genre, Java y compris.
    Si read() te renvoie quelque chose, c'est qu'il y a quelque chose à renvoyer : soit un octet reçu, soit que la socket est fermée.

    Si tu "n'envoies rien" et que tu ne fermes pas la socket, alors read() reste bloquée, point final.
    Conclusion : ce n'est pas ça qui se passe. Tu fais sans doute quelque chose qui ferme la socket.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 9
    Dernier message: 23/03/2010, 10h14
  2. Réponses: 3
    Dernier message: 20/10/2006, 19h50
  3. Comment définir un timeout sur une socket PHP ?
    Par N3odyme dans le forum Langage
    Réponses: 7
    Dernier message: 07/05/2006, 23h04
  4. Comment spécifier des raccourcis claviers sur une Form ?
    Par Sydaze dans le forum Composants VCL
    Réponses: 5
    Dernier message: 17/06/2005, 09h05
  5. comment faire fonctionner l'exe sur une autre machine
    Par brian79 dans le forum C++Builder
    Réponses: 8
    Dernier message: 28/05/2004, 14h00

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