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

Qt Discussion :

QTcpSocket read : pas de données


Sujet :

Qt

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 20
    Points : 8
    Points
    8
    Par défaut QTcpSocket read : pas de données
    Bonjour,

    J'ai un problème de réception de données avec mon appli client:

    J'ai essayé de suivre l'exemple : http://qt.developpez.com/doc/4.5/network-fortuneclient/

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    void MainWindow::readServerData()
    {
        QDataStream in(_tcpSocket);
          qDebug() << "bytesAvailable " << _tcpSocket->bytesAvailable();
            if (_tcpSocket->bytesAvailable() == 0)
                return;
     
        QString data;
        in >> data;
        qDebug() << "data " << data;
    }
    Le serveur envois la chaine suivante "hello"
    Le packet tcp est bien reçu, la fonction est appelée.
    Le nombre de byte est correcte, mais impossible d'afficher le contenu.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    bytesAvailable  6 
    data  "
    Quelqu'un aurait-il une idée?

  2. #2
    Membre expérimenté
    Avatar de FloMo
    Homme Profil pro
    Freelance iOS
    Inscrit en
    Juillet 2004
    Messages
    726
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations professionnelles :
    Activité : Freelance iOS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2004
    Messages : 726
    Points : 1 511
    Points
    1 511
    Par défaut
    Utiliser QByteArray au lieu de QString ?

  3. #3
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Points : 2 161
    Points
    2 161
    Par défaut
    Citation Envoyé par Ferllings Voir le message
    Le serveur envois la chaine suivante "hello"
    Visiblement, le string n'a pas été encodé côté serveur avec le même principe (QDataStream), qui utilise ce format d'encodage:
    QString
    * If the string is null: 0xFFFFFFFF (quint32)
    * Otherwise: The string length in bytes (quint32) followed by the data in UTF-16
    Ici, pour 'hello', on aurait plutôt dû recevoir 14 octets: 4 octets (32bits) pour la taille du string et (ici) chacune des 5 lettres encodée sur 2 octets (cf. UTF-16.

    Ce qui m'amène à penser que le string a probablement été encodée en tant que 'dump' direct d'un char* (6 octets = 5 lettres de 'hello' plus le caractère de fin '\0').

    Donc on en revient à la proposition de FloMo: passer par un QByterArray pour récupérer les 6 octets, puis utiliser le constructeur QString(QByteArray) pour retrouver ton 'hello' de départ.

    A noter qu'en utilisant une telle méthode d'encodage côté serveur, tu vas très vite être bloqué avec les caractères ne faisant pas partie de l'ASCII standard (genre '€'). Il est plus que conseillé d'encoder en passant par les QString côté serveur également.

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 20
    Points : 8
    Points
    8
    Par défaut
    J'ai essayé ca, mais j'obtiens le même résultat.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    QByteArray data;
        _tcpSocket->read(data.data(), data.size());
          qDebug() << "bytesAvailable " << _tcpSocket->bytesAvailable();
        qDebug() << "data " << data;

  5. #5
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Salut,
    si tu veut pouvoir lire ta string envoyé, il faut que bytesAvailable() retourne un nombre >= à la taille de ta string. Sinon tu va faire des lecture corrompu.
    En principe, on ajoute la taille de l'élément envoyé en début del'envoie. A la réception, on lit ainsi la taille à attendre et l'on fait une récupération une fois ce nombre de byte atteins.
    regarde les exemple deans Qt, il montre le principe :
    http://qt.developpez.com/doc/4.4/network-fortuneserver/
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    QByteArray block;
         QDataStream out(&block, QIODevice::WriteOnly);
         out.setVersion(QDataStream::Qt_4_0);
         out << (quint16)0;
         out << fortunes.at(qrand() % fortunes.size());
         out.device()->seek(0);
         out << (quint16)(block.size() - sizeof(quint16));

    http://qt.developpez.com/doc/4.4/network-fortuneclient/
    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
         QDataStream in(tcpSocket);
         in.setVersion(QDataStream::Qt_4_0);
     
         if (blockSize == 0) {
             if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))
                 return;
     
             in >> blockSize;
         }
     
         if (tcpSocket->bytesAvailable() < blockSize)
             return;
     
         QString nextFortune;
         in >> nextFortune;

  6. #6
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Points : 2 161
    Points
    2 161
    Par défaut
    La solution proposée par yan est effectivement indispensable pour ne pas corrompre à terme ton flux de données.

    Citation Envoyé par Ferllings Voir le message
    J'ai essayé ca, mais j'obtiens le même résultat
    Pour info, dans ton cas précis, le nombre d'octets et assez restreint pour qu'il soit envoyé dans un seul paquet, donc l'origine du problème ne venait pas de ce que t'explique (à raison) yan.

    Mais, dans ton exemple de code, tu initialises un QByteArray sans paramètre qui, d'après la doc:
    Constructs an empty byte array.
    C'est donc un QByteArray qui a une taille de ... zéro octets.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    _tcpSocket->read(data.data(), data.size());
    Donc, la ligne ci-dessus ne va lire ... rien du tout car data.size() vaut zéro !

    CQFD.

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 20
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par yan Voir le message
    Salut,
    si tu veut pouvoir lire ta string envoyé, il faut que bytesAvailable() retourne un nombre >= à la taille de ta string. Sinon tu va faire des lecture corrompu.
    En principe, on ajoute la taille de l'élément envoyé en début del'envoie. A la réception, on lit ainsi la taille à attendre et l'on fait une récupération une fois ce nombre de byte atteins.
    regarde les exemple deans Qt, il montre le principe :
    http://qt.developpez.com/doc/4.4/network-fortuneserver/
    Merci Yan mais tu n'as pas du comprendre ma question:
    Je suis justement parti de ces examples pour mon client.
    Mais dans mon cas ca ne fonctionnait pas vu que je n'ai pas de contrôle sur le serveur, et qu'il envoit des caractères dans un encodage different.
    C'est pourquoi on m'a conseillé d'utiliser QByteArray.
    En se qui concerne la taille de la donnée envoyée je m'en occuperais une fois que j'aurais reussi à reçevoir quelques caractères

  8. #8
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    ha ok.
    Ben il faut pas passer par une QString alors

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 20
    Points : 8
    Points
    8
    Par défaut
    Bon ben ca n'a pas l'air d'un problème d'encodage:

    J'ai essayé de connecter mon client au fortuneServer avec ce code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
          qDebug() << "bytesAvailable " << _tcpSocket->bytesAvailable();
         QDataStream in(_tcpSocket);
         in.setVersion(QDataStream::Qt_4_0);
         QString data;
         in >> data;
        qDebug() << "data " << data;
    Et le problème est le même:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    bytesAvailable  118 
    data  ""
    Par contre le fortuneClient fonctionne bien.
    Je vais essayer de voir quelles sont les differences entre mon client et le fortuneClient.
    Ya forcement qqchose que je fais mal.

  10. #10
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    ce sont des caractère 8bit ou 16bit?

    [edit]
    il ne faut pas utiliser QString car DataStream les écrit d'une certaine manière pour pouvoir les relire. Donc si ton text est envoyé d'une autre manière, tu ne peut pas lire une QString

  11. #11
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 20
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par yan Voir le message
    il ne faut pas utiliser QString car DataStream les écrit d'une certaine manière pour pouvoir les relire. Donc si ton text est envoyé d'une autre manière, tu ne peut pas lire une QString
    J'ai justement voulu verifier cela en utilisant un QString(code du fortuneClient) et en connectant le fortuneServer. Vu que ce sont les 2 mêmes encodage, ca aurait du fonctionner.
    Mais vu que ce n'est pas le cas, j'en deduis que mon problème vient d'ailleur.

    Je cherche...

  12. #12
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par Ferllings Voir le message
    J'ai justement voulu verifier cela en utilisant un QString(code du fortuneClient) et en connectant le fortuneServer. Vu que ce sont les 2 mêmes encodage, ca aurait du fonctionner.
    Mais vu que ce n'est pas le cas, j'en deduis que mon problème vient d'ailleur.

    Je cherche...
    y as deux problème:
    * ce que doit lire DataStream
    * ex ce que ce que doit lire Datastream est arrivé.

    Si c'est une chaîne de caractère, faire une lecture caractère par cractère. D'où ma question caractère 8bit ou 16 bit.
    un truc comme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    QDataStream in(_tcpSocket);
     
    QString resultat;
    quint8 c;
    while(...)
    {
        if (tcpSocket->bytesAvailable() >= sizeof(quint8 ))
        {
           in >> c;
          resultat+= c;
        }
    ...
    }

  13. #13
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 20
    Points : 8
    Points
    8
    Par défaut
    Ca avance:

    J'ai utilisé un int16, comme je teste toujours avec le fortuneServer.
    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
     
    QDataStream in(_tcpSocket);
     
    QString resultat;
    quint16 c;
    while(_tcpSocket->bytesAvailable() > 0)
    {
        if (_tcpSocket->bytesAvailable() >= sizeof(quint16 ))
        {
           in >> c;
           char h = c;
           qDebug() << _tcpSocket->bytesAvailable() << " (" << c << ") (" << h << ")";
          resultat+= c;
        }
    }
    qDebug() << "data " <<  resultat.size() <<" (" << resultat<< ")";
    Apparement le Qstring contient bien tous les caractères.
    Mais ensuite c'est le Qdebug qui n'arrive pas à l'afficher à cause du '0'.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    44  ( 44 ) ( , ) 
    42  ( 0 ) ( 
    40  ( 40 ) ( ( ) 
    38  ( 89 ) ( Y ) 
    ...
    ...
    4  ( 105 ) ( i ) 
    2  ( 108 ) ( l ) 
    0  ( 46 ) ( . ) 
    data  23  ( ",
    Merci pour votre aide, maintenant que j'ai cerné le problème, je pense que j'arriverais à convertir tout ca.

Discussions similaires

  1. pb de syntaxe XML ne reconnais pas les données ..
    Par lolodelp dans le forum XML/XSL et SOAP
    Réponses: 1
    Dernier message: 19/06/2006, 12h24
  2. y'a pas les données quand je veux imprimer
    Par StyleXP dans le forum Bases de données
    Réponses: 38
    Dernier message: 25/03/2006, 20h15
  3. probleme XPath, j'obtiens pas ma données ?
    Par Bruno13 dans le forum Langage
    Réponses: 7
    Dernier message: 02/02/2006, 15h25
  4. XMLEncoder ne sauvegarde pas la donnée d'un PlainDocument.
    Par mitje dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 27/01/2006, 05h06
  5. [ORA-01403] Pas de données trouvées ; et alors ?
    Par szdavid dans le forum Oracle
    Réponses: 6
    Dernier message: 02/08/2005, 12h20

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