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 :

Socket et lecture du flux


Sujet :

Entrée/Sortie Java

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2005
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2005
    Messages : 21
    Points : 18
    Points
    18
    Par défaut Socket et lecture du flux
    Bonjour,

    Je suis actuellement occupé a me créer une classe FTP en Java. Non que les API existantes ne me plaisent pas, mais ca me fait mon petit tutorial perso par la même occasion.

    J'ai 2 soucis sur lesquels j'aimerai avoir l'avis d'expert svp :

    1°) Voici la fonction Connect de ma classe :

    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
    	public boolean Connect() throws Exception{	 
     
    		m_progress=true;
                    //...
    		socket.connect(m_address, 5000);
    		Thread.sleep(waitTime); //wait for connecting
    		//Ici je suis obligé de faire un sleep du thread de qq ms et ce à chaque envoi de données également ... 
    		istream = socket.getInputStream();
    		ostream = socket.getOutputStream();
     
    		m_reply=ReadData();
     
    		m_progress=false;	
     
    		if(m_replyVal!=220){
    			m_connected=false;
    			CloseSocket();
    			return false;
    		}			
    		else{
    			m_connected=true;
    			fireFTPSocketStateChanged(SocketState.Connected, SocketType.Normal);
    			return true;
    		}
    	}
     
    private void SendData(String data) throws Exception{
    		ostream.write((data+"\r\n").getBytes());
    		ostream.flush();
    		if(debug) System.out.println("Sent : " + data);
    		Thread.sleep(waitTime); //Egalement ici je dois faire un sleep pour pouvoir entammer la lecture de la réponse
    		m_reply = ReadData();
    	}
    Pouvez-vous me dire pourquoi à chaque envoi de données ou connect je suis obligé de faire un Thread.sleep avant de pouvoir lire la réponse ?

    J'aime pas trop faire de sleep dans un Thread ca ralentit quand même l'exécution . Est-ce que je fais quelque chose de pas correct ?


    2. Dans le cas suivant je recois des données concaténées sur mon flux réseau :

    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
    public String[] GetFilelist(String Mask) throws Exception
        {
            m_progress = true;
            //....
     
            String[] list;
            String msg="";
     
            Socket DataSocket = CreateDataSocket();
     
            fireFTPEventMessage("LIST " + Mask,Way.Outgoing,-1);
            SendData("LIST " + Mask);
            // C'est ici que je recois ma réponse 150, et je recois dans la foulée la 226 que la liste est envoyée ... 
            if (!(m_replyVal== 150 || m_replyVal== 125))
            {
                Disconnect();
                throw new IOException("Error sending LIST Command - " + m_reply);
            }
     
            fireFTPEventMessage("Opening Data Connection ...", Way.System,-1);
     
            OutputStream out = DataSocket.getOutputStream();
            out.flush();
     
          	InputStream in = DataSocket.getInputStream();
     
     
            while(in.available()!=0){
    			int bytes=in.read(m_buffer, 0, m_buffer.length);
    			msg += new String(m_buffer,0,bytes);
    			if(debug) System.out.println("Message Received : " + msg);
    		}
     
            list = msg.split("\r\n");
     
            fireFTPEventMessage("Closing Data Connection",Way.System,-1);
            DataSocket.close();
            fireFTPSocketStateChanged(SocketState.Closed,SocketType.Normal);
     
            Thread.sleep(waitTime);
     
            //m_reply= ReadData();
     
            if (m_replyVal!= 226)
            {
                throw new IOException("Problem closing Data Connection : " + m_reply.substring(4));
            }
            m_progress = false;
            return list;
        }
    Pourquoi est-ce que les messages reçus après "LIST *" sont concaténés ?

    J'exécute ce même code en c# (même exercice que j'avais fait à l'époque en c#) et la ca marche bien ...


    Merci de votre aide,

    Looney

  2. #2
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    Pour info le protocole FTP est définis ici

    http://www.ietf.org/rfc/rfc959.txt
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2005
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2005
    Messages : 21
    Points : 18
    Points
    18
    Par défaut
    Bonjour, et merci beaucoup pour le lien vers le rfc, mais je le connais ...

    Mais ca ne réponds pas trop à la question.

    Pourquoi en C# cela marche sans les Thread.sleep et en Java pas ? Il y a-t-il quelque chose qui manque?

    Ensuite, je suppose que le RFC c'est pour la commande LIST que vous me mettez le lien.

    Seulement le 150 (Data Transfert starting) et le 226 (Directory successfully sent) sont reçu dans la premiere lecture du stream (avant la lecture du socket data ...)

    Merci à vous,

    Looney

  4. #4
    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
    1) Que se passe-t-il sans le sleep? D'ou viens ce socket, que font readData et CloseSocket?
    2) Qu'entends tu par 'concaténées' ? Le flux d'un socket est quelque chose de continu, tant que le serveur envoie tu recevra des truc à lire. C'est à toi ensuite d'en séparer les différents éléments. Si tu veux lire ligne par ligne, branche un bufferedreader dessus.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2005
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2005
    Messages : 21
    Points : 18
    Points
    18
    Par défaut
    Bonjour,

    1. Justement après tous mes essais, je me suis aperçu que je devais mettre un sleep à cet endroit afin de pouvoir commencer la lecture du stream reçu. Autrement je ne lisais rien.

    Pour la var 'socket' :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    m_address=new InetSocketAddress(m_host,m_port);
    		socket = new Socket();
    CloseSocket s'occupe simplement de faire un logoff et cloturer le socket s'il est encore ouvert. Rien de plus.

    pour ReadData:

    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
    private String ReadData() throws Exception{
    		int receivedbytes;
    		String msg="";
     
    		while(istream.available()!=0){
    			receivedbytes=istream.read(m_buffer, 0, m_buffer.length);
    			msg += new String(m_buffer,0,receivedbytes);
    			if(debug) System.out.println("Message Received : " + msg);
    		}
    		if(msg.equals("")){
    			m_replyVal=-1;
    			return msg;
    		}
    		else{
    			m_replyVal = ReplyValue(msg);
    			fireFTPEventMessage(msg,Way.Incoming, m_replyVal);
    			return msg;	
    		}
    	}
     
    	private int ReplyValue(String msg){
    		int returnVal=0;
     
    		returnVal = Integer.parseInt(msg.substring(0,3));
    		return returnVal;
    	}
    2. Concatené est que par exemple, je reçois à l'envoi de la commande "LIST" la réponse suivante :

    150 Opening data connection for directory list.
    226 Transfer complete.

    Et ce en une seule lecture du flux réseau, hors je n'ai même pas encore lancer la lecture du socket data.

    Normalement la séquence est :

    > Envoi LIST
    < Rep 150
    < Lecture du flux data pour la liste
    < Rep 226 Transfert Complet.

    Hors ici j'ai :

    > Envoi LIST
    < Rep 150 + 226 concatené.
    < Lecture du flux data pour la liste
    < Rep 226 (mais la ca bloque car je l'ai déjà recu dans ma premiere lecture de la réponse).

    Et quand je test cette même séquence en c# (de la ou vient ma classe) ca marchait bien.

    J'éspère que c'est plus clair.

    Merci,

    Looney

  6. #6
    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
    on va essyaé de répondre dans l'ordre. Ton erreur qui t'oblige à faire le sleep est là:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    		while(istream.available()!=0)
    Ce test te permet de savoir si des données sont disponible. Comme tu viex d'envoyer une commande au serveur, il n'est pas dit que le serveur t'as déjà envoyé la réponse, donc available peux renvoyer false. Il peux envoyer aussi false même si t'as pas encore tout reçu, en cas de congestion. Ce test permet seulement de savoir si, lors du prochain read, l'appel sera bloquant ou non. Ca ne sert à rien d'autre. Dans ton cas tu devrais plutot faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int read;
    byte[] bufer=....:
    while ( (read=istream.read(buffer))!=-1){
      // on a des données à traiter
    }
    Voir les docs sur les inputstream en java pour plus de détail sur comment lire un stream
    Ce code bien sur en supposant une connection jettable (tu l'ouvre, tu lit tout, ca se ferme). Mais il me semble me souvenir que les connection de donnée ftp sont comme ça.

    Quand à la concaténation, vu que ftp utilise deux stream (un pour le controle, un pour les datas), je suppose que tu recois les deux réponse du serveur ftp (150 et 226) avec quelques millisecondes d'écart mais que tu n'a pas eu le temps de lire le 150 avant que le serveur t'aie envoyé le 226. Comme déjà dit, c'est à toi de séparer les différents éléments, un stream c'est continu. Comme en ftp c'est un élément / ligne avec des \n en fin de ligne, tu peux utiliser un BufferedReader et sa méthode readLine pour te faciliter le travail.

Discussions similaires

  1. Lecture / Ecriture Flux (Fichier, socket, etc.)
    Par LittleT dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 26/01/2013, 11h05
  2. [Java][Socket] Pas de lecture de flux
    Par mavina dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 20/10/2006, 19h02
  3. lecture de flux video dans borderLayout.CENTER
    Par Dsphinx dans le forum Multimédia
    Réponses: 5
    Dernier message: 04/08/2006, 17h30
  4. [Audio] Enregistrement et lecture de flux...
    Par remixtech dans le forum Langage
    Réponses: 2
    Dernier message: 29/10/2005, 12h07
  5. Erreur de lecture du flux sous SQLServer
    Par smazaudi dans le forum Bases de données
    Réponses: 4
    Dernier message: 29/03/2005, 14h30

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