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 :

Transmission/Réception partielle de structure via socket


Sujet :

Réseau C

  1. #21
    Expert éminent sénior

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    as-tu déjà vu un '\n' ou un traitement ne tenant pas compte de realloc dans le code de HTTP ????

    ou pensant que tout est arrrivé sur un seul recv ??
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  2. #22
    Expert éminent sénior

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Je dirais "structure binaire mal conçue", car binaire ne veut pas dire non-évolutif (exemple concret : payload d'une trame Ethernet / IP / UDP / TCP, vraiment au hasard).
    Certes, c'est plus contraignant en binaire qu'en ASCII.
    sans doute, mais si c'est un champ au milieu de la structure qui est modifié, en binaire ça crashe.. quelle que soit la "version" que tu aies pu mettre..


    Maintenant, il est certain que si le programmeur n'avait pas prévu le "unrecognized keyword" ou au contraire la transformation avec le bon keyword en passant d'une version supérieure à une version inférieure, on n'y peut rien..

    Mais une bonne conception ASCII sera plus souple qu'une bonne conception binaire par rapport à l'évolution / maintenance..
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  3. #23
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    as-tu déjà vu un '\n' ou un traitement ne tenant pas compte de realloc dans le code de HTTP ????
    Je n'ai regardé le code d'aucune implémentation de HTTP. Dans tous les cas, je n'ai pas dit qu'il n'y en avait pas, seulement qu'il était ch***t d'avoir à en mettre.

    Et encore, je pense personnellement que pas mal de vieilles implémentations doivent avoir un buffer de taille fixe pour les lignes d'en-tête: L'erreur 414 existe pour une raison, après tout.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #24
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    as-tu déjà vu un '\n' ou un traitement ne tenant pas compte de realloc dans le code de HTTP ????
    C'est justement là le problème : avoir un realloc... Et pour HTTP, effectivement, ça ne sera pas "\n" qui sera vérifié, mais "\r\n".
    Et pour avoir écrit de mes p'tites mains musclées un serveur HTTP, un serveur FTP, un client SMTP et moult clients/serveurs Telnet, je te garantis que tu as "un peu" intérêt à tenir compte du facteur "taille maximale des lignes", ou à prier Sainte-Fragmentation de foutre la paix à ton heap...

    Citation Envoyé par souviron34 Voir le message
    sans doute, mais si c'est un champ au milieu de la structure qui est modifié, en binaire ça crashe.. quelle que soit la "version" que tu aies pu mettre..
    C'est pour ça que j'ai mis "version" ET longueur... Pas de crash dans un tel cas, pour plusieurs raisons :
    - La taille empêche d'émettre / recevoir trop de données et de provoquer donc un buffer overrun.
    - La version interdit de décoder une trame que l'on ne sait PAS décoder (version plus récente que celle du code).

    Citation Envoyé par souviron34 Voir le message
    Mais une bonne conception ASCII sera plus souple qu'une bonne conception binaire par rapport à l'évolution / maintenance..
    Plus souple, c'est pas gagné non plus. Plus lisible / parlante, éventuellement. Plus facile à examiner par un humain "on-wire", c'est une évidence.

    Mais la version ASCII peut être plus difficile à implémenter que la version binaire, et poser bien plus de soucis... Entre d'une part le "réglage" d'une déclaration de structure (alignement + endianness) et ensuite un code qui tape bourrinement dedans, et d'autre part un décodage syntaxique ET sémantique d'un flux texte, il y a plus qu'une nuance, et côté temps de développement, y'a pas photo non plus... Pour l'ASCII, par exemple, si tu ne parles pas à une machine ayant la même taille de mot-machine, tu commences déjà assez mal pour le décodage des entiers / flottants, sans même aborder la problématique de l'encodage des caractères eux-même...
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  5. #25
    Expert éminent sénior

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    C'est justement là le problème : avoir un realloc... Et pour HTTP, effectivement, ça ne sera pas "\n" qui sera vérifié, mais "\r\n".
    Et pour avoir écrit de mes p'tites mains musclées un serveur HTTP, un serveur FTP, un client SMTP et moult clients/serveurs Telnet, je te garantis que tu as "un peu" intérêt à tenir compte du facteur "taille maximale des lignes", ou à prier Sainte-Fragmentation de foutre la paix à ton heap...

    C'est pour ça que j'ai mis "version" ET longueur... Pas de crash dans un tel cas, pour plusieurs raisons :
    - La taille empêche d'émettre / recevoir trop de données et de provoquer donc un buffer overrun.
    - La version interdit de décoder une trame que l'on ne sait PAS décoder (version plus récente que celle du code).

    Plus souple, c'est pas gagné non plus. Plus lisible / parlante, éventuellement. Plus facile à examiner par un humain "on-wire", c'est une évidence.

    Mais la version ASCII peut être plus difficile à implémenter que la version binaire, et poser bien plus de soucis... Entre d'une part le "réglage" d'une déclaration de structure (alignement + endianness) et ensuite un code qui tape bourrinement dedans, et d'autre part un décodage syntaxique ET sémantique d'un flux texte, il y a plus qu'une nuance, et côté temps de développement, y'a pas photo non plus... Pour l'ASCII, par exemple, si tu ne parles pas à une machine ayant la même taille de mot-machine, tu commences déjà assez mal pour le décodage des entiers / flottants, sans même aborder la problématique de l'encodage des caractères eux-même...
    je ne me prendrais pas la tête avec toi là dessus..

    Nous avons des expériences différentes, et ma conclusion diffère..

    Néanmoins juste un problème par rapport au binaire :

    inclure la taille ne change rien à l'affaire..

    Si la structure comprend : entier + char + char*4 + double + entier

    Et que tu la transfomes en : entier + char + double + entier + char*4


    la taille restera identique mais la lecture binaire crashera...



    C'est juste ce que je voulais dire.. : il te faut OBLIGATOIREMENT recompilation de l'ensemble des exécutables concernés..



    Et comme, dans ce cas, il y aura toujours, dans chaque exécutable, une routine ReadStructure et un autre WriteStructure, que tu le lises en ASCII ou en binaire sera (si c'est fait proprement, avec des htonl etc) de toutes façons non immédiat.. ce qui faciliterait grandement la "compatibilité" si c'était transmis en ASCII par mot-clé, puisque le "découpage" élément par élément de la structure est déjà fait...

    M'enfin, tout ça était pour dire pr rapport à la remarque initiale de Médinoc..

    NON la taille n'est pas un problème...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  6. #26
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    Néanmoins juste un problème par rapport au binaire :
    inclure la taille ne change rien à l'affaire..
    Si la structure comprend : entier + char + char*4 + double + entier
    Et que tu la transfomes en : entier + char + double + entier + char*4
    la taille restera identique mais la lecture binaire crashera...
    Oui, il faut les deux, version ET taille :
    • Premier cas : version(1) + taille(22) + entier + char + char*4 + double + entier
    • Deuxième cas : version(2) + taille(22) + entier + char + double + entier + char*4
    • La taille protège l'overrun => pas de crash à ce niveau.
    • La version interdit d'exploiter le contenu de la structure (qui sera bien entendu totalement incohérent sans l'union adéquate permettant de décoder la 2ème variante).
    Bref, pas de problème...

    Citation Envoyé par souviron34 Voir le message
    Et comme, dans ce cas, il y aura toujours, dans chaque exécutable, une routine ReadStructure et un autre WriteStructure, que tu le lises en ASCII ou en binaire sera (si c'est fait proprement, avec des htonl etc) de toutes façons non immédiate..
    Certes. Mais entre quelques correction d'endianness et la sérialisation sous forme de texte de N valeurs flottantes (par exemple), il y a une grosse différence dans le temps d'exécution ET dans le temps de réalisation du code, de façon à gérer tous les cas possibles... Et si ton endianness host est identique à celle attendue par le protocole, ça se finit avec un send bovin.

    Citation Envoyé par souviron34 Voir le message
    M'enfin, tout ça était pour dire pr rapport à la remarque initiale de Médinoc..

    NON la taille n'est pas un problème...
    Ben si, pourtant... Soit par épuisement de ta RAM à coup de realloc (ce qui correspond à une attaque du serveur / client en règle, d'ailleurs), soit via un refus type 414, soit encore par une usine à gaz gérant le flux en tant que tel (et non plus ligne à ligne comme le protocole l'impose dans le cas des précités).

    C'est très exactement la même problématique que la lecture d'un fichier texte ligne à ligne, d'ailleurs... Sujet hautement récurrent sur le forum, comme tu le sais très bien.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  7. #27
    Expert éminent sénior

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Oui, il faut les deux, version ET taille :
    • Premier cas : version(1) + taille(22) + entier + char + char*4 + double + entier
    • Deuxième cas : version(2) + taille(22) + entier + char + double + entier + char*4
    • La taille protège l'overrun => pas de crash à ce niveau.
    • La version interdit d'exploiter le contenu de la structure (qui sera bien entendu totalement incohérent sans l'union adéquate permettant de décoder la 2ème variante).
    Bref, pas de problème...
    Simplement parce que tu supposes que dans le code il est prévu "si VERSION > MaVERSION" alors ne fait rien...

    En général les vérifications se passent par négociations vers la version la plus basse, si un système de version a été prévu.

    Mais de toutes façons, cela suppose la gestion de version, ce qui n'était pas le problème exposé ci-dessus..

    Je continue à affirmer : dans un code "normal", qui (surtout pour des passages en binaire de structure) ne prévoit pas de versions, se passer des structures en binaires est très largement plus pénalisant en souplesse et maintenance que se les passer en ASCII...


    Citation Envoyé par Mac LAK Voir le message
    Certes. Mais entre quelques correction d'endianness et la sérialisation sous forme de texte de N valeurs flottantes (par exemple), il y a une grosse différence dans le temps d'exécution ET dans le temps de réalisation du code, de façon à gérer tous les cas possibles... Et si ton endianness host est identique à celle attendue par le protocole, ça se finit avec un send bovin.
    Je ne comprend pas ce point...

    Les routines de lecture et d'écriture doivent passer à travers tous les champs de la structure un par un pour faire les appels aux hton ou ntoh..

    Quel est le poids différent de l'écrire dans un buffer ??





    Citation Envoyé par Mac LAK Voir le message
    Ben si, pourtant... Soit par épuisement de ta RAM à coup de realloc (ce qui correspond à une attaque du serveur / client en règle, d'ailleurs), soit via un refus type 414, soit encore par une usine à gaz gérant le flux en tant que tel (et non plus ligne à ligne comme le protocole l'impose dans le cas des précités).

    C'est très exactement la même problématique que la lecture d'un fichier texte ligne à ligne, d'ailleurs... Sujet hautement récurrent sur le forum, comme tu le sais très bien.
    Encore une fois, je ne vois pas le point..

    On ne parle pas ici d'envoyer un fichier ligne à ligne, on parle de transmettre une structure....

    Et encore une fois, un protocole établi empêche tout simplement ton "attaque"... Mais de toutes façons le problème n'est pas dans une attaque.. Le sujet ici n'est pas le piratage, mais comment passer des données d'un programme à un autre via socket...


    Et je continue à penser que la réponse donnée est hors de propos par rapport à la question posée...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  8. #28
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Évidemment, bien sûr que passer des structures non-sérialisées est dangereux. On n'est pas idiots quand même.

    Mais je préfère toujours sérialiser en binaire plutôt qu'en texte. Même en supposant un système de valeurs nommées, j'utiliserais un format binaire, du genre:
    taille totale(u32, valeur 0xFFFFFFFF réservée) + nombre de variables(u32) + ( taille nom(u16) + nom ( + autres infos) taille données(u32) + données ) * (nombre de variables)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #29
    Expert éminent sénior

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    eh bien moi non..

    J'utiliserais un protocole ASCII de token...



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Nom_VAR1 val1 Nom_VAR2 Val2 ...
    Comme ça, les structures et les binaires sont indépendants..

    Un peut stocker Var1 en réel l'autre en entier si il en a plus l'utilité..


    Mais aussi on peut par exemple supprimer l'envoi d'un token sans rien changer aux autres binaires..

    Ou en rajouter sans pour autant modifier TOUS les programmes, mais juste ceux qui doivent l'utiliser (dans un premier temps évidemment, avant de tous les remettre à jour)..

    C'est juste une pratique de développement/maintenance souple...


    Cela n'empêche pas de tout recompiler quand on souhaite la version défintiive à la même version..

    ça implique simplement que l'on peut procéder (tester, debugger, etc) par étapes.. (et en particulier pour les très gros projets où la compilation totale est très longue)...

    ça implique aussi que l'on peut se permettre d'être multi-versions, avec plusieurs clients par exemple...


    ça m'est arrivé.. Tu fais une amélioration, mais 2 clients sur 3 ne la veulent pas, ou pas maintenant (par exemple ils sont en cours de produire quelque chose, et veulent comparer des choses comparables)..

    Tout ce qui se passe, c'est que simplement le "nouveau" token n'est pas reconnu par eux, mais est reconnu par le client qui a bien voulu avoir l'update..



    PS: et on peut retomber sur la notion de compatibilité et la discussion à propos de IE6
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  10. #30
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Le format binaire que j'ai ici esquissé n'empêche en rien l'ajout ou la suppression de valeurs nommées, et je me suis bien gardé de mentionner le format des valeurs elles-mêmes: Ce qui importe pour moi, c'est qu'elles soient précédées de leur taille, et que cette taille ait elle-même une taille (plus ou moins) fixe.

    Oh, et avec ça, on n'a pas de problèmes de séparateurs.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #31
    Expert éminent sénior

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Le format binaire que j'ai ici esquissé n'empêche en rien l'ajout ou la suppression de valeurs nommées, et je me suis bien gardé de mentionner le format des valeurs elles-mêmes:
    Non, mais il est plus long (puisque par exemple tu passes le nombre de variables)


    Mais de toutes façons, je ne crois pas que c'est ce qui était entendu par "passage en binaire de structures", ou alors on se comprend très mal....


    Ce qui est pratiqué en général dans ce cas, c'est soit le "dump" total en binaire (fwrite), soit le "dump" modulé avec les hton ou ntoh par champ...


    Et cette pratique est, je le répète, ce qui s'est passé au début des années 90, mais est très lourde de conséquences pour la maintenance et la souplesse...



    Maintenant, si tu fais un protocole en passant un nom de variable en ASCII, que la valeur elle-même tu la passes en binaire ou non c'est identique de mon point de ve, à la conversion près, qui, sur une structure, ne va pas consommer du temps...

    Ce dont je parlais est d'une communication de structures SANS protocole ASCII...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  12. #32
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Dans ce cas, je suis d'accord avec toi: Le passage de structures non-sérialisées, c'est le mal.

    Généralement, j'ai tendance à utiliser une sérialisation "rigide", mais je vais suivre mon propre conseil et utiliser une sérialisation "souple" à partir de maintenant, pour mes prochains protocoles.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #33
    Membre émérite Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 021
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 021
    Points : 2 278
    Points
    2 278
    Par défaut
    Désolé d'interrompre ce débat très intéressant
    Je voudrais donc définir une structure et je vais passer par une union mais mon schéma de requête est du type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    requete 0 :
    data_a
     
    requete 1 :
    data_a + data_b + data_c
     
    requete 2 :
    data_a + data_b + data_c + data_d + data_e
    plutôt qu'un choix réel entre les différentes données, il s'agit d'un ajout. Avec une union ça me donnerait un truc du style :

    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
    union donnees {
    	struct donnees_1 {
    		int data_a;
    	};
    	struct donnees_2 {
    		int data_a;
    		int data_b;
    		int data_c;
    	};
    	struct donnees_3 {
    		int data_a;
    		int data_b;
    		int data_c;
    		int data_d;
    		int data_e;
    	};
    };
    Je me retrouve donc avec des définitions assez lourdes et dupliquées.
    Auriez-vous une idée sur la question pour mutualiser tout ça ?
    Je pensais à quelque chose comme ça, mais qui ne me semble pas très propre :

    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
    union donnees {
    	typedef struct donnees_1 {
    		int data_a;
    	} d1;
    	typedef struct donnees_2 {
    		donnees_1 d1;
    		int data_b;
    		int data_c;
    	} d2;
    	struct donnees_3 {
    		donnees_2 d2;
    		int data_d;
    		int data_e;
    	};
    };
    Car ensuite, on a une hiérarchie de structures qui complexifie la réception.

    D'autre part, je savais que HTTP, SMTP, etc. fonctionnaient via ASCII mais quelqu'un pourrait-il me dire pourquoi on a alors plus de problème d'alignement lors de l'envoi de données sur différentes machines/OS ?

    Merci d'avance.

    [edit] Je précise quand même que je n'envoie pas que des int
    Vive les roues en pierre

  14. #34
    Expert éminent sénior

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    euh...

    Pourquoi pas simplement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct donnees {
                              int Present[5] ;
     
    		int data_a;
    		int data_b;
    		int data_c;
    		int data_d;
    		int data_e;
    }
    ou toute autre structure équivalente ???


    J'aimerais que tu clarifies ton problème..

    Là tu sembles avoir des requêtes différentes, qui chacune utilise des données différentes..

    Mais tes données, tu les as de part et d'autre, c'est bien ça ?

    Elles ne sont pas imbriquées, mais successives , indépendantes ?

    En quoi faire des strutures de données imbriquées résoudra-t-il le rpoblème ?


    Si tu peux avoir les 4 ou N) données simultanément, faire une union et un peu absurde..

    Soit tu fais une strcuture comme j'ai mentionné plus haut, soit tu peux aussi faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct donnees {
              int type ;
              int data ;
    }
    et manipuler un tableau de données, par exemple...



    Citation Envoyé par Djakisback Voir le message
    Dé[edit] Je précise quand même que je n'envoie pas que des int
    Mais alors c'est une union de types de valeur, qu'il te faut, pas une union d'ensembles de données..


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef union pValue ({
         int i ;
         double d ;
         char c ;
         char *s ;
    } Value ;
    Avec ou non inclusion du type suivant que tu veux le faire explicitement ou non, et/ou que tu veux le passer via le protocole ou non...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  15. #35
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    Simplement parce que tu supposes que dans le code il est prévu "si VERSION > MaVERSION" alors ne fait rien...
    Tout comme tu supposes que ton client ne va planter s'il ne trouve pas un champ requis, ou qu'au contraire il en trouve un non-prévu... Si tu supposes que c'est implémenté par un goret, quoi que tu conçoives, ça va planter de toutes façons !!

    Citation Envoyé par souviron34 Voir le message
    Je continue à affirmer : dans un code "normal", qui (surtout pour des passages en binaire de structure) ne prévoit pas de versions, se passer des structures en binaires est très largement plus pénalisant en souplesse et maintenance que se les passer en ASCII...
    La question étant plutôt "pourquoi ne PAS mettre d'informations de taille / version" de façon générale... Prévoir l'évolutivité n'est pas spécialement une option, à mon sens, que ce soit en binaire ou en ASCII.

    Citation Envoyé par souviron34 Voir le message
    Quel est le poids différent de l'écrire dans un buffer ??
    Si tu le sérialises en ASCII, il est pourtant clair et net qu'un htonl est nettement plus rapide et moins pénalisant à faire qu'un sprintf, et c'est encore pire lors de la réception : scanf n'est pas un modèle de légèreté à gérer, tu le sais très bien.

    Citation Envoyé par souviron34 Voir le message
    On ne parle pas ici d'envoyer un fichier ligne à ligne, on parle de transmettre une structure....
    Tu peux appeler "ligne" ce que tu veux : une chaîne AZT, une chaîne terminée par CR/LF, ça n'a aucune importance. Dans tous les cas, tu DOIS pouvoir déterminer la fin de ligne (= d'entité) pour savoir quand la réception est terminée.

    Citation Envoyé par souviron34 Voir le message
    Le sujet ici n'est pas le piratage, mais comment passer des données d'un programme à un autre via socket...
    Certes. Mais pour envoyer une structure, il est quand même bien de savoir quand elle est terminée. En binaire, c'est la taille des données qui te le dit. En ASCII, c'est comment ? D'où la problématique des tailles de buffer en réception que l'on évoquait précédemment.

    Citation Envoyé par souviron34 Voir le message
    J'utiliserais un protocole ASCII de token...
    ... Ce qui est extrêmement pénalisant côté bande passante, quand même, il faut en être conscient, et encore plus pénalisant côté (dé)sérialisation si l'on se contente des fonctions C classiques. Même en C++, ce n'est pas une sinécure, il n'y a guère que dans les langages de script que c'est une chose (relativement) simple à traiter.

    Citation Envoyé par souviron34 Voir le message
    ça implique simplement que l'on peut procéder (tester, debugger, etc) par étapes.. (et en particulier pour les très gros projets où la compilation totale est très longue)...
    Comme tu le sais certainement, c'est justement mon cas quotidien. Or, je ne fais au contraire QUE des envois binaires, notamment pour permettre à des éléments plus "faibles" en puissance de calcul de pouvoir malgré tout traiter un volume de données suffisant.

    Citation Envoyé par souviron34 Voir le message
    Et cette pratique est, je le répète, ce qui s'est passé au début des années 90, mais est très lourde de conséquences pour la maintenance et la souplesse...
    C'est pourtant toujours d'actualité, cf. TCP/IP et Ethernet... Et IPv6 n'est pas mieux à ce sujet.

    Citation Envoyé par souviron34 Voir le message
    Ce dont je parlais est d'une communication de structures SANS protocole ASCII...
    Citation Envoyé par Djakisback Voir le message
    Auriez-vous une idée sur la question pour mutualiser tout ça ?
    Tu peux faire un truc dans ce genre, aussi :
    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
    union donnees {
      struct donnees_1 {
        int data_a;
      };
      struct donnees_2 {
        struct donnees_1 d1;
        int data_b;
        int data_c;
      };
      struct donnees_3 {
        struct donnees_2 d2;
        int data_d;
        int data_e;
      };
    };
    Toutefois, cela reste une solution d'envoi binaire "brut", bien entendu.

    Citation Envoyé par Djakisback Voir le message
    D'autre part, je savais que HTTP, SMTP, etc. fonctionnaient via ASCII mais quelqu'un pourrait-il me dire pourquoi on a alors plus de problème d'alignement lors de l'envoi de données sur différentes machines/OS ?
    Parce qu'à part si elle est en Unicode, ce qui n'est pas le cas de ces protocoles, une chaîne de caractères est composée d'éléments d'un seul octet, les caractères, et n'est donc pas sensible à l'endianness, tout simplement.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  16. #36
    Membre émérite Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 021
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 021
    Points : 2 278
    Points
    2 278
    Par défaut
    Ok, merci bien, je vais rester sur définitions dupliquées
    Pour ce qui est de l'ASCII, c'est ce que je pensais merci.

    @souviron34 : en fait ce que je voulais dire c'est que ma requête de type 1 par exemple utilise les mêmes variables que la requête de type 0 plus d'autres variables. La requête de type 2 les mêmes que la requête 1 plus d'autres, etc.
    Vive les roues en pierre

  17. #37
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Djakisback Voir le message
    Ok, merci bien, je vais rester sur définitions dupliquées
    La duplication, c'est le mal. Soit tu réutilises des structures déjà définies, soit tu utilises une structure "universelle" (définissant TOUT), avec des #define ou des constantes pour définir la taille à envoyer (et donc n'envoyer qu'une partie de la structure).
    Mais définir deux fois la même chose à deux endroits différents, c'est s'exposer à un risque non négligeable de régression en cas d'évolution.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  18. #38
    Membre émérite Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 021
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 021
    Points : 2 278
    Points
    2 278
    Par défaut
    Hmm, donc tu me conseillerais de faire comme ça :

    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
    union donnees {
      struct donnees_1 {
        int data_a;
      };
      struct donnees_2 {
        struct donnees_1 d1;
        int data_b;
        int data_c;
      };
      struct donnees_3 {
        struct donnees_2 d2;
        int data_d;
        int data_e;
      };
    };
    plutôt que comme ça ?
    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
     
    union donnees {
    	struct donnees_1 {
    		int data_a;
    	};
    	struct donnees_2 {
    		int data_a;
    		int data_b;
    		int data_c;
    	};
    	struct donnees_3 {
    		int data_a;
    		int data_b;
    		int data_c;
    		int data_d;
    		int data_e;
    	};
    };
    quittes à complexifier pas mal le code de réception ?
    Vive les roues en pierre

  19. #39
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Djakisback Voir le message
    Hmm, donc tu me conseillerais de faire comme ça :
    ...
    quittes à complexifier pas mal le code de réception ?
    Oui, même s'il n'est pas si complexifié que ça : le code de traitement du type 3 de requête reste celui du type 3, non-impacté par le code des autres requêtes. Par rapport à ta méthode, ça ne fait que rajouter un ".d1" ou un ".d2" en plus dans l'identifiant de ton champ, au final, et mettre dans une fonction le codage/décodage des sous-structures si nécessaire de façon à capitaliser le code.

    Mais au moins, à condition qu'il soit normal que les premiers champs du 3ème type de requête soit les mêmes que les champs des requêtes "précédentes", la modification des données de la requête 1 modifiera automatiquement les requêtes 2 et 3, alors que dans ta méthode, tu devras le modifier trois fois.

    Si par contre ce n'est qu'un heureux hasard, alors ta solution par duplication est préférable, car la requête 1 pourrait évoluer sans impacter la requête 3 par exemple.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  20. #40
    Membre émérite Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 021
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 021
    Points : 2 278
    Points
    2 278
    Par défaut
    Oui effectivement mais là je me retrouve avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct d3 {
    			struct d1 d_1;			// Lecture
    			struct d2 d_2;			// Ecriture
    		} d_3;
    Ce qui me donne des manipulations de ce style pour assigner des variables :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    scanf("%s", buffer);
    strcpy(req.d.d_3.d_1.d_0.data_a, atoi(buffer));
    Et j'aurai le même problème à la réception par le serveur.
    Je garde donc ta solution dans un coin mais sur ce coup-là je vais m'en tenir à la duplication, c'est loin d'être un projet important (merci encore)
    Vive les roues en pierre

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réception et envoie simultané via la même socket
    Par deripaske dans le forum Réseau
    Réponses: 2
    Dernier message: 01/03/2011, 18h29
  2. Envoi d'une structure via sockets
    Par milanoran dans le forum C++
    Réponses: 8
    Dernier message: 17/11/2010, 14h19
  3. Envoi de structure via socket
    Par RoZyk dans le forum Réseau
    Réponses: 4
    Dernier message: 09/11/2010, 10h01
  4. Réponses: 0
    Dernier message: 06/03/2009, 21h31
  5. [C#] Problème transmission via socket
    Par LE NEINDRE dans le forum Windows Forms
    Réponses: 2
    Dernier message: 11/07/2006, 08h29

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