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

C++ Discussion :

C++ Socket envoi de structures s�rialis�es


Sujet :

C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    F�vrier 2011
    Messages
    3
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 3
    Par d�faut C++ Socket envoi de structures s�rialis�es
    Bonjour a tous,

    Dans le cadre d'un projet scolaire je dois coder un serveur tcp qui est cens� r�ceptionner des structures sur le r�seau via socket TCP. Je ne suis pas autoris� a utiliser de librairies type Qt ou Boost pour la s�rialisation ou pour le r�seau.

    Mon probl�me est que les donn�es que je re�oit sont corrompues. Excuser moi pour la longueure du code que je m'appr�te a poster mais si vous voulez avoir une chance de m'aider il vous faut tout les �l�ments.

    La structure que j'envoie ( c'est Packet) :
    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
     
    struct Header
    {
      uint32_t      magic;
      uint32_t      checksum;
      uint32_t      timestamp;
      uint16_t      commandId;
      uint16_t      dataSize;
    };
     
    struct Packet
    {
      struct Header header;
      char          data[128];
    };
    Je s�rialise cette structure avec ces fonctions
    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
     
    unsigned char                           *Serialization::serialize_uint32(unsigned char *buffer, uint32_t arg)
    {
      buffer[3] = (arg >> 24);
      buffer[2] = (arg >> 16);
      buffer[1] = (arg >> 8);
      buffer[0] = (arg);
      return (buffer + sizeof(uint32_t));
    }
     
    unsigned char                           *Serialization::serialize_uint16(unsigned char *buffer, uint16_t arg)
    {
      buffer[1] = (arg >> 8);
      buffer[0] = (arg);
      return (buffer + sizeof(uint16_t));
    }
     
    unsigned char                           *Serialization::serialize_char(unsigned char *buffer, char arg)
    {
      buffer[0] = (arg);
      return (buffer + sizeof(char));
    }
     
    unsigned char                           *Serialization::serialize_string(unsigned char *buffer, char *arg, int len)
    {
      int                           i;
     
      i = -1;
      while (++i < len)
        buffer = serialize_char(buffer, arg[i]);
      return (buffer);
    }
     
    unsigned char                           *Serialization::serialize_header(unsigned char *buffer, struct Header& arg)
    {
      buffer = serialize_uint32(buffer, arg.magic);
      buffer = serialize_uint32(buffer, arg.checksum);
      buffer = serialize_uint32(buffer, arg.timestamp);
      buffer = serialize_uint16(buffer, arg.commandId);
      buffer = serialize_uint16(buffer, arg.dataSize);
      return (buffer);
    }
     
    unsigned char                           *Serialization::serialize_packet(unsigned char *buffer, struct Packet& arg)
    {
      buffer = serialize_header(buffer, arg.header);
      buffer = serialize_string(buffer, arg.data, arg.header.dataSize);
      return (buffer);
    }
    je d�s�rialise ainsi :
    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
     
    unsigned char                           *Serialization::deserialize_uint32(unsigned char *buffer, uint32_t *arg)
    {
      memcpy((char*)arg, buffer, sizeof(uint32_t));
      *arg = ntohl(*arg);
      return (buffer + sizeof(uint32_t));
    }
     
    unsigned char                           *Serialization::deserialize_uint16(unsigned char *buffer, uint16_t *arg)
    {
      memcpy((char*)arg, buffer, sizeof(uint16_t));
      return (buffer + sizeof(uint16_t));
    }
     
    unsigned char                           *Serialization::deserialize_char(unsigned char *buffer, char *arg)
    {
      memcpy(arg, buffer, sizeof(char));
      return (buffer + sizeof(char));
    }
     
    unsigned char                           *Serialization::deserialize_string(unsigned char *buffer, char *arg, int len)
    {
      memcpy(arg, buffer, len);
      return (buffer + len);
    }
     
    unsigned char                           *Serialization::deserialize_header(unsigned char *buffer, struct Header& arg)
    {
      buffer = deserialize_uint32(buffer, &arg.magic);
      buffer = deserialize_uint32(buffer, &arg.checksum);
      buffer = deserialize_uint32(buffer, &arg.timestamp);
      buffer = deserialize_uint16(buffer, &arg.commandId);
      buffer = deserialize_uint16(buffer, &arg.dataSize);
      return (buffer);
    }
     
    unsigned char                           *Serialization::deserialize_packet(unsigned char *buffer, struct Packet& arg)
    {
      buffer = deserialize_header(buffer, arg.header);
      buffer = deserialize_string(buffer, arg.data, arg.header.dataSize);
      return (buffer);
    }
    Le code d'envoi de mon client est :
    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
     
    TcpSocket                     tcp;
    Packet                        p;
    char                          *serialized;
     
    tcp.connectSocket("127.0.0.1", 4242);
    p.header.magic = 0;
    p.header.checksum = 1;
    p.header.timestamp = 2;
    p.header.commandId = 3;
    p.header.dataSize = ss.str().length();
    memset(p.data, 0, 128);
    memcpy(p.data, "0", 2);
    serialized = new char[sizeof(Header) + 2];
    bzero(serialized, sizeof(Header) + 2);
    Serialization::serialize_packet(serialized, p);
    hexDump("serialized", serialized+1, sizeof(Header) + 2);
    ret = tcp.write(serialized, sizeof(Header) + 3);
    et mon serveur recoit ainsi (cette fonction est appell� par la boucle sur le select()) :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
     
    int bav;
     
    bav = socket->bytesAvailable();
    buff = new char[bav];
    socket->read(buff, bav);
    hexdump("buff", buff, bav);
    methodes read et send de ma classe Socket :
    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
     
    int                     TcpSocket::read(char *buff, int len)
    {
      int                   ret;
     
      ret = recv(this->_socket, buff, len, 0);
      return (ret);
    }
     
    int                     TcpSocket::bytesAvailable()
    {
      int                   ret;
      char                  buff[65536];
     
      ret = recv(this->_socket, buff, 65535, MSG_PEEK);
      return (ret);
    }
     
    int                     TcpSocket::write(const std::string& buff, int len)
    {
      int                   ret;
     
      ret = send(this->_socket, buff.c_str(), len, 0);
      return (ret);
    }
    voici les deux hexdumps :

    client :
    00 00 00 00 00 00 01 00 00 00 02 00 03 00 01 30 ...............0

    server:
    00 00 00 00 14 00 00 00 1c 00 00 00 1a 00 00 00 ...............

    J'ai cherch� pendant plusieurs jours avant de venir vous ennuyer avec mon probl�me.
    En vous remerciant par avance

  2. #2
    Expert �minent

    Femme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    D�tails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (�le de France)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par d�faut
    Quand tu d�serialises, tu utilises memcopy directement, donc tu devrait en faire autant avec serialise.

    Ton probl�me, c'est que l'endianess est fix� dans ta serialisation (big endian) mais pas dans la deserialisation.
    Comme je parie que ta machine est little endian, tu te fais avoir.

    En g�n�ral, quand on code deux op�rations duales, il faut s'assurer que le code est bien sym�trique.

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    F�vrier 2011
    Messages
    3
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 3
    Par d�faut
    Je suis d'accord avec toi sur un point. Je devrais d�s�rialiser en d�callage binaire mes donn�es, mais je n'ai pas r�ussi a la faire.
    Avec memcpy, quand je s�rialise et d�serialise mon Packet dans un meme scope, je retrouve tout mes donn�es intactes.
    Si je me faisais avoir par l'endianess mes donn�es devrais �tre strictement invers�es or dans le hexdump que je fournis 01 n'est pas la sym�trie de 14

  4. #4
    Membre chevronn�
    Homme Profil pro
    Java
    Inscrit en
    Mai 2011
    Messages
    170
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 35
    Localisation : France, Val de Marne (�le de France)

    Informations professionnelles :
    Activit� : Java
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Mai 2011
    Messages : 170
    Par d�faut
    Sinon ne pas oublier les middle-endian s'il-vous-pla�t. Peut �tre pas r�pandu mais �a existe et qui sait ;-)

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    F�vrier 2011
    Messages
    3
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 3
    Par d�faut
    J'effectue tous mes test en localhost, donc l'endianess (dans mon cas) n'est pas la source d'erreur

  6. #6
    Membre Expert

    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 49
    Localisation : France, Bouches du Rh�ne (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : High Tech - Op�rateur de t�l�communications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par d�faut
    Citation Envoy� par leternel Voir le message
    Quand tu d�serialises, tu utilises memcopy directement, donc tu devrait en faire autant avec serialise.

    Ton probl�me, c'est que l'endianess est fix� dans ta serialisation (big endian) mais pas dans la deserialisation.
    Comme je parie que ta machine est little endian, tu te fais avoir.

    En g�n�ral, quand on code deux op�rations duales, il faut s'assurer que le code est bien sym�trique.
    D�s lors que l'endianness s'en m�le, memcpy risque de faire des choses �tranges Avec l'av�nement de toutes les plateformes ARM (big endian par d�faut) dans le monde du mobile, il est peut-�tre judicieux de faire les choses correctement. Et les choses correctes ne sont pas compliqu�es, vu qu'on nous fournit les fonction qui doivent �tre utilis�es : htonl/htons et ntohl/ntohs (h = host, n = network : l = long (32 bits), s = short (16 bits)).

    Quand on envoie des entiers sur le r�seau : htonl/s ; pour les r�cup�rer du r�seau, la fonction inverse ntohl/s. Ces fonctions garantissent que les donn�es qui circulent sont dans un boutisme d�termin� (boutisme r�seau : big endian), et qu'on les transforme syst�matiquement pour un usage sur le host.
    [FAQ des forums][FAQ D�veloppement 2D, 3D et Jeux][Si vous ne savez pas ou vous en �tes...]
    Essayez d'�crire clairement (c'est � dire avec des mots fran�ais complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Caf�. C'est d�pass� tout �a.
    Et si vous �tes sages, vous aurez peut �tre vous aussi la chance de passer � la t�l�. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

Discussions similaires

  1. Envoi de structure via socket
    Par RoZyk dans le forum R�seau
    R�ponses: 4
    Dernier message: 09/11/2010, 10h01
  2. windows socket, probl�me envoi de structure :s
    Par ramislebob dans le forum R�seau
    R�ponses: 7
    Dernier message: 29/07/2006, 23h17
  3. [SOCKET] Envoi de structure
    Par Lolita59 dans le forum R�seau
    R�ponses: 3
    Dernier message: 17/05/2006, 15h30
  4. [toFAQ][socket] Envoi d'une structure
    Par julien20vt dans le forum C++
    R�ponses: 15
    Dernier message: 23/04/2003, 15h47
  5. [Socket]envoie de fichier!!!
    Par SamDaKap dans le forum C++Builder
    R�ponses: 5
    Dernier message: 20/11/2002, 08h07

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