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

Réseau Discussion :

Faire dialoguer socket C et socket Qt


Sujet :

Réseau

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 5
    Par défaut Faire dialoguer socket C et socket Qt
    Bonjour,

    voila presque tout est dans le titre ^^. Je cherche à faire dialoguer (en TCP) un serveur Qt avec un client écrit en C (oui je sais ce n'est pas forcément l'idéal). A première vue j'ai bien un échange sauf que je n'arrive pas à lire correctement les données.

    le client C envoi une structure (avec un send) du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    struct Message {int a, int b, char[BUFSIZ] m};
    et le serveur Qt la lit avec QDataStream et l'opérateur >> surchargé.

    Le résultat est que je reçois 2 entiers, qui n'ont rien a voir avec ceux émis, et une chaine vide, alors qu'elle ne l'était pas. Je pense à un problème de décalage de bits mais je ne vois pas comment résoudre ce problème.

    Est ce que vous pouvez me donner un coup de main ?

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Il me semble que QDataStream utilise un format binaire qui lui est propre pour l'échange des données. Donc, je ne suis pas sur que tu puisses utiliser un simple send(socket,&my_struct,sizeof(my_struct)) (de toute façon, il faudrait te préoccuper de l'endianness et des l'alignement).

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 5
    Par défaut
    D'accord,
    j'ai pensé a regardé du coté de TcpSocket avec les méthodes read*, mais je n'ai eu plus de succès.
    Est ce que vous savez s'il existe des méthodes pour lire des données émises en C ?

  4. #4
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Bonjour makuta et bienvenu sur le forum Qt

    Ce qu'il faut comprendre, c'est que struct Message aura une structure interne en mémoire qui dépend de la plateforme et donc envoyer directement cette structure avec send ne sera pas portable.
    Le but de la sérialisation (QDataStream, boost::serialize, etc.) est de créer un paquet de données qui ne sera pas plateforme-dépendant. Il utilise en général un format spécifique, qui sera en général compatible qu'avec lui même. Par exemple, QDataStream code les char* en ajoutant un quint32 en en-tête sans \0 terminal. Et les int seront convertit en qintXXX en fonction de la plateforme (et ne seront donc pas portable).

    Tu peux lire directement un paquet de x octets avec readRawData. Mais ça ne fonctionnera que si les formats binaires de tes structures sont identiques entre ton émetteur et ton récepteur ("il faudrait te préoccuper de l'endianness et des l'alignement" comme dit 3DArchi). Si ton émetteur doit fonctionner sur plusieurs plateformes différentes, ça devient très compliqué de gérer la réception.

    Si les programmes tournent sur les mêmes plateformes, essaies de lire directement (mode barabare) le paquet d'octet.

    émetteur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    struct Message {int a, int b, char[BUFSIZ] m};
    send(socket,&my_struct, sizeof(my_struct));
    réception :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct Message {int a, int b, char[BUFSIZ] m};
    Message data;
    const int buffer_size = sizeof(int) * 2 + sizeof(char) * BUFSIZ; 
       // je ne sais plus si la norme impose char = 1 octet donc par défaut...
       // en espérant que l'alignement ne pose pas de problème...
    QDataStream in(&tcp_socket);
    char* buffer = static_cast<char*>(&data);
    if (in.readRawData(buffer, buffer_size) == -1)
       // erreur
    else
       // ok
    Mais c'est vraiment du code sale

    L'idéal est d'utiliser une lib de sérialisation dans l'émetteur.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 5
    Par défaut
    J'ai essayé votre solution, elle fonctionne, j'ai juste rajouté un cast en char* dans le static_cast et j'en ai utilisé un 2eme pour convertir le buffer en Message.

    Par contre a quoi sert le static_cast (j'utilise plus le const_cast ou le dynamic_cast que celui la)

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Comme te l'a dit gbdivers, cette approche est problématique : la taille des types natifs peut varier d'une plateforme à l'autre, ainsi que le boutisme et les contraintes d'alignements. On n'échange jamais des structures telles quelles mais on se défini un petit 'protocole' de sérialisation !

    Pour ta question sur les casts : F.A.Q : Comment effectuer une conversion de type explicite (cast) ?

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 5
    Par défaut
    Dans la mesure où mon programme ne tourne qu'en local (le programme fait de la simulation) il ne devrait pas y avoir de problème au niveau de la lecture des paquet. si ?

    Pour le protocole de sérialisation ça serait par exemple rajouter un certain nombre de bits lors de l'émission et de les enlever pour désérialiser ?

Discussions similaires

  1. Faire un timeout sur un socket
    Par Hastur dans le forum Tcl/Tk
    Réponses: 1
    Dernier message: 13/05/2009, 13h53
  2. Quel langage pour faire un serveur avec des sockets
    Par CocoLeNain dans le forum Services
    Réponses: 3
    Dernier message: 15/03/2008, 18h04
  3. socket client c# <-> socket serveur c++
    Par g0up1l dans le forum C#
    Réponses: 7
    Dernier message: 23/10/2007, 18h17
  4. VB6 Comment Faire : "Dialogue entre 2 machines"
    Par C_Mila dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 16/03/2007, 14h59
  5. Faire dialoguer deux EXE (non activex)
    Par Vld44 dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 27/11/2006, 15h35

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