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 C Discussion :

Envoi de structure


Sujet :

Réseau C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 10
    Par défaut Envoi de structure
    Bonjour,
    J'ai déjà fait du réseau en C & C++ en codant quelque clients et serveurs pour des usages différents (POP, SMTP..), mais à chaque fois je me contentais d'envoyer du texte (via send et recv).
    Dans le cadre d'envoi de son, j'aimerai être capable d'envoyer (et de recevoir) des structures. J'ai pas mal cherché sur le net et j'ai trouvé des termes tel que "serialisation" ou "protocol binaire" (je n'ai pour l'instant utilisé que des protocoles textuels).
    Ma question est donc, comment gérer dans la pratique l'envoi de structure? Et que signifie un protocole binaire exactement (je pensais à l'envoi de chaine composée de 0 & de 1, mais vu le peu d'intérêt que cela représente, j'imagine que j'ai faux).
    Merci d'avance.
    Cordialement,
    Jonnyd

  2. #2
    Membre Expert Avatar de fregolo52
    Homme Profil pro
    Développeur C
    Inscrit en
    Août 2004
    Messages
    2 366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Août 2004
    Messages : 2 366
    Par défaut
    tu dois sérialiser si ta structure contient des pointeurs.

    Je ne sais pas comment est structuré un son, mais si c'est une suite de nombres complexes, ça n'est pas bien compliqué.

    Donc, peux-tu nous montrer la déclaration de ta structure ?

  3. #3
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Un protocole texte est un protocole dans lequel on envoie des commandes sous forme de chaine de caractères. Les protocoles POP, SMTP et HTTP sont d'excellents exemples de tels protocoles.

    Un protocole binaire est, par opposition à un protocole texte, un protocole dans lequel les données envoyées sont des valeurs binaires ou encore des octets dont les valeurs peuvent valoir entre 0 et 255. Les protocoles SSH ou X11 sont des protocoles binaires.

    Si dans un protocole texte, le marqueur de fin d'une commande (ou de réponse) est en général (mais pas toujours) le caractère ASCII CR ou CRLF, dans un protocole binaire, il n'y a pas de marqueur de fin de commande (ou de réponse). Il faut donc que l'émetteur et le récepteur se synchronisent autrement.

    Cette méthode de synchronisation fait partie du protocole et on trouve plusieurs types de synchronisation.

    On peut envoyer d'abord la longueur de la commande (ou de la réponse) et ensuite les valeurs binaires de cette commande (ou réponse).

    On peut utiliser aussi un identifiant de commande (ou de réponse). Par exemple, si le premier octet vaut 8, il s'agit alors d'une commande du type "blabla" et le programme récepteur sait alors qu'il faut lire 28 octets. Le protocole X11 fonctionne comme cela. Il faut alors identifier toutes les commandes et toutes les réponses et attribuer un identifiant différent à chacune des requêtes et des commandes.

    En ce qui concerne la sérialisation, je vais appuyer mon exemple sur la structure suivante à envoyer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    typedef struct
    { int Valeur;
       unsigned char Foo;
       char * Chaine;
       int Tag;
       char * Attribut;
    } Structure_t;
    Il y a plusieurs pièges à prendre en compte lors de l'envoi d'une telle structure :
    1. Les pointeurs : un pointeur n'a de sens que pour le programme qui "tient" la structure. Ce pointeur ne doit pas être transmis car il n'aurait aucun sens pour le programme récepteur. Il faut donc transmettre les données pointées par ce pointeur et surtout pas le pointeur lui même. Pour ce type de données et si elles ont une longueur variable, il convient en plus de transmettre la longueur des données.
    2. Le boutisme : certaine machines utilisent pour les nombre un boutisme "poids fort en premier", d'autre un boutisme "poids faible en premier" (en général, c'est lié au micro processeur et à l'organisation de la mémoire). On parle de boutisme "Big Endian" ou "Little Endian". Il faut que le protocole entre l'émetteur et le récepteur prenne en compte cette différence possible d'organisation des nombre.
    3. L'alignement : suivant les architectures, les champs d'une structure sont alignés avec du padding appelés aussi "octets de bourrage" afin que les différents champs de la structure soient correctement alignés sur des frontière mémoire. Ainsi, sur une architecture 32 bits, un nombre 32 bits sera aligné sur une frontière multiple de 4. Le même nombre de 32 bits sur une architecture 64 bits risque d'être aligné sur une frontière multiple de 8. La conséquence de ceci est que la taille d'une structure (retourné par l'opérateur sizeof()) sur 2 architecture différentes risque fort d'être différentes.


    Une fois que tous ces pièges sont connus, l'envoi de la structure est plus facile :
    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
    Structure_t MaStructure;
    int val;
     
    // envoi du champs 'Valeur'
    val = htonl(MaStructure.Valeur);
    send(sock, &val, sizeof(val));
     
    // envoi du champs 'Foo'
    send(sock, &MaStructure.Foo, sizeof(MaStructure.Foo));
     
    // envoi du champs 'Chaine'
    val = htonl(strlen(MaStructure.Chaine));
    send(sock, &val, sizeof(val));
    send(sock, MaStructure.Chaine, strlen(MaStructure.Chaine));
     
    // envoi du champs 'Tag'
    val = htonl(MaStructure.Tag);
    send(sock, &val, sizeof(val));
     
    // envoi du champs 'Attribut'
    val = htonl(strlen(MaStructure.Attribut));
    send(sock, &val, sizeof(val));
    send(sock, MaStructure.Attribut, strlen(MaStructure.Attribut));
    Bien sûr, cette fonction est a adapter en fonction de la structure à envoyer.

    En ce qui concerne la réception, cela donnerait un truc comme cela :
    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
    Structure_t MaStructure;
    int val;
     
    // réception du champs 'Valeur'
    recv(sock, &val, sizeof(val));
    MaStructure.Valeur = ntohl(val);
     
    // réception du champs 'Foo'
    recv(sock, &val, sizeof(val));
    MaStructure.Foo = val;
     
    // réception du champs 'Chaine'
    recv(sock, &val, sizeof(val));
    MaStructure.Chaine = malloc(nthol(val) + 1;
    recv(sock, MaStructure.Chaine, nthol(val));
    MaStructure.Chaine[nthol(val)] = 0;
     
    ...
    La procédure de réception doit être rigoureusement le pendant de la procédure d'émission.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  4. #4
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    il faut d'autre part utiliser les fonctions hton.. et ntoh... (hosttonetwork et networktohost) pour tenir compte automatiquement des problèmes d'indianess..

    Par exemple

    htonl

  5. #5
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Il y a plusieurs pièges à prendre en compte lors de l'envoi d'une telle structure :
    1. Les pointeurs : un pointeur n'a de sens que pour le programme qui "tient" la structure. Ce pointeur ne doit pas être transmis car il n'aurait aucun sens pour le programme récepteur. Il faut donc transmettre les données pointées par ce pointeur et surtout pas le pointeur lui même. Pour ce type de données et si elles ont une longueur variable, il convient en plus de transmettre la longueur des données.
    2. Le boutisme : certaine machines utilisent pour les nombre un boutisme "poids fort en premier", d'autre un boutisme "poids faible en premier" (en général, c'est lié au micro processeur et à l'organisation de la mémoire). On parle de boutisme "Big Endian" ou "Little Endian". Il faut que le protocole entre l'émetteur et le récepteur prenne en compte cette différence possible d'organisation des nombre.
    3. L'alignement : suivant les architectures, les champs d'une structure sont alignés avec du padding appelés aussi "octets de bourrage" afin que les différents champs de la structure soient correctement alignés sur des frontière mémoire. Ainsi, sur une architecture 32 bits, un nombre 32 bits sera aligné sur une frontière multiple de 4. Le même nombre de 32 bits sur une architecture 64 bits risque d'être aligné sur une frontière multiple de 8. La conséquence de ceci est que la taille d'une structure (retourné par l'opérateur sizeof()) sur 2 architecture différentes risque fort d'être différentes.
    Ne pas oublier la taille des types qui peut être différente d'une architecture à l'autre.

  6. #6
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Citation Envoyé par gl Voir le message
    Ne pas oublier la taille des types qui peut être différente d'une architecture à l'autre.
    Pas faux !!

    Pour moi, le seul type dont la taille peut être différente est le type int.

    Les autres types (signed char, unsigned char, signed short int, unsigned short int, signed long int, unsigned long int, signed long long int et unsigned long long int) ont des tailles identiques sur toutes les architectures.

    J'ai faux ?
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  7. #7
    Membre Expert Avatar de fregolo52
    Homme Profil pro
    Développeur C
    Inscrit en
    Août 2004
    Messages
    2 366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Août 2004
    Messages : 2 366
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Pour moi, le seul type dont la taille peut être différente est le type int.
    Oula !!! Tu n'as jamais fait de multi plate-formes !!!!
    Go wikipedia.
    On a découvert ça en bossant sur XP et SUSE x64, on ne comprenait pas pourquoi le sizeof des structures étaient différents sur les 2 OS alors qu'on n'avait aucun 'int', on en est tombé sur le cul.

    Ce qui vaut dire que ce qu'on apprend à l'école est un peu faux :
    int : CPU dépendant
    long : 4 octets

    Ca dépend de l'architecutre du CPU et de l'OS.

    Je crois qu'il y a aussi un souci de padding entre les 2 OS quand tu as des 'char' au milieu de la strucutre.

  8. #8
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Pas faux !!

    Pour moi, le seul type dont la taille peut être différente est le type int.

    Les autres types (signed char, unsigned char, signed short int, unsigned short int, signed long int, unsigned long int, signed long long int et unsigned long long int) ont des tailles identiques sur toutes les architectures.

    J'ai faux ?
    Citation Envoyé par fregolo52 Voir le message
    Oula !!! Tu n'as jamais fait de multi plate-formes !!!!
    Go wikipedia.
    On a découvert ça en bossant sur XP et SUSE x64, on ne comprenait pas pourquoi le sizeof des structures étaient différents sur les 2 OS alors qu'on n'avait aucun 'int', on en est tombé sur le cul.

    Ce qui vaut dire que ce qu'on apprend à l'école est un peu faux :
    int : CPU dépendant
    long : 4 octets

    Ca dépend de l'architecutre du CPU et de l'OS.

    Je crois qu'il y a aussi un souci de padding entre les 2 OS quand tu as des 'char' au milieu de la strucutre.
    d'où l'usage des hton et ntoh ...

  9. #9
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Les autres types (signed char, unsigned char, signed short int, unsigned short int, signed long int, unsigned long int, signed long long int et unsigned long long int) ont des tailles identiques sur toutes les architectures.
    Non, le C ne garantie que la plage minimale que doit supporter un type donnée, aucune taille n'est garantie.

    En pratique, il est plus ou moins probable de rencontrer des différences en fonction du type, mais aucun n'a une taille fixe.

    Une autre différence à prendre en compte est la différence de codage pour les entiers négatifs ou les nombres réels.

  10. #10
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Je reprends mon post d'il a quelques jours en le complétant avec les remarques et oublis qui m'ont été signalés (et en corrigeant les quelques fautes d'orthographe) :

    Il y a plusieurs pièges à prendre en compte lors de l'envoi d'une telle structure :

    • Les pointeurs : un pointeur n'a de sens que pour le programme qui "tient" la structure. Ce pointeur ne doit pas être transmis car il n'aurait aucun sens pour le programme récepteur. Il faut donc transmettre les données pointées par ce pointeur et surtout pas le pointeur lui même. Pour ce type de données et si elle a une longueur variable, il convient en plus de transmettre la longueur des données.
    • Le boutisme : certaine machines utilisent pour les nombres un boutisme "poids fort en premier", d'autre un boutisme "poids faible en premier" (en général, c'est lié au micro processeur et à l'organisation de la mémoire). On parle de boutisme "Big Endian" ou "Little Endian" (il existe même le boutisme Middle Endian). Il faut que le protocole entre l'émetteur et le récepteur prenne en compte cette différence possible d'organisation des nombres. Il convient d'utiliser les fonctions hton*() et ntoh*() pour gérer ces problèmes.
    • L'alignement : suivant les architectures, les champs d'une structure sont alignés avec du padding appelés aussi "octets de bourrage" afin que les différents champs de la structure soient correctement alignés sur des frontières mémoire. Ainsi, sur une architecture 32 bits, un nombre 32 bits sera aligné sur une frontière multiple de 4. Le même nombre de 32 bits sur une architecture 64 bits risque d'être aligné sur une frontière multiple de 8. La conséquence de ceci est que la taille d'une structure (retourné par l'opérateur sizeof()) sur 2 architecture différentes risque fort d'être différente.
    • La taille des types de données qui peut être différente d'une architecture ou d'un compilateur à l'autre. Une variable de type "int" peut faire 32 bits sur une architecture et 64 bits sur une autre architecture.
    • Les différents codages utilisés pour représenter les nombres signés (position du bit de signe dans le nombre) ou les nombres flottants (IEEE 754, autre norme).


    PS : Peut être que ce post mériterait une petite place dans la
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  11. #11
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Citation Envoyé par Jonnyd Voir le message
    Ma question est donc, comment gérer dans la pratique l'envoi de structure? Et que signifie un protocole binaire exactement (je pensais à l'envoi de chaine composée de 0 & de 1, mais vu le peu d'intérêt que cela représente, j'imagine que j'ai faux).
    J'ajoute (parce que ça va mieux en le disant) qu'un protocole « texte » est quand même en soi un protocole binaire, dans le sens où les caractères envoyés sont en fait les codes correspondants dans le jeu de caractères en cours, généralement ASCII, et qu'ils sont envoyés sous forme de 0 et de 1 comme tout le reste.

    L'idée est que, lorsque l'on parle de protocole texte, on sait que les données transmises sont des caractères affichables, et que la manière de les transmettre va respecter quelques règles élémentaires, notamment l'utilisation de retours à la ligne. Tout ceci permettant, en principe, de dialoguer « humainement » avec le client en face (en utilisant telnet, par exemple) ou, à tout le moins, de pouvoir visualiser directement les données.

    Par opposition, quand on parle de « données binaires », on entend souvent par là : « rien de plus structuré à première vue qu'une suite de 0 et de 1 ». En général, ces données le sont quand même, mais n'ont de sens qu'au niveau du client et ne peuvent pas être interprétées par ce qui se trouve entre les deux.

    C'est une terminologie qui est apparue naturellement aux informaticiens, pratiquement depuis le début, et qui est restée sur pratiquement toutes les générations d'ordinateurs. On l'applique également à la gestion des fichiers.

Discussions similaires

  1. Envoi de structure
    Par katcha95 dans le forum GTK+ avec C & C++
    Réponses: 4
    Dernier message: 03/06/2010, 23h57
  2. Envoie de structure à un thread.
    Par mohdaef dans le forum Threads & Processus
    Réponses: 2
    Dernier message: 24/03/2008, 17h23
  3. envoi de structure en MPI
    Par fatjoe dans le forum C++
    Réponses: 5
    Dernier message: 08/03/2008, 15h04
  4. windows socket, problème envoi de structure :s
    Par ramislebob dans le forum Réseau
    Réponses: 7
    Dernier message: 29/07/2006, 23h17
  5. [SOCKET] Envoi de structure
    Par Lolita59 dans le forum Réseau
    Réponses: 3
    Dernier message: 17/05/2006, 15h30

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