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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Par défaut Transmission/Réception partielle de structure via socket
    Bonjour,
    pourrait-on me confirmer que la continuité des données en mémoire d'une structure n'est pas garantie ? Mon idée est la suivante pour la définition d'une structure de requête de client à serveur. Mettons que pour une requête de type 0 on doive transmettre data1 et pour une requête de type 1 on doive transmettre data1 et data2 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef struct {
    	int requestType; 		
    	int data1;
    	char[20] data2;
    	//etc...
    } request;
    Le client envoie toujours la même structure mais pas forcément en entier, ex :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    request req;
    //...
    // Type 0, envoi de requestType et data1 uniquement (2 int)
    ret = send(socket, (void*)&req, sizeof(int) * 2, 0);
     
    // Type 1, envoi de requestType, data1 et data 2
    ret = send(socket, (void*)&req, sizeof(int) * 2 + sizeof(char) * 20, 0);
    Et du côté du serveur la réception se fait en fonction de requestType, ex :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    request req;
    //...
    // Réception du type de requête
    ret = recv(socket, (void*)req->requestType, sizeOf(req.requestType), 0);
    // Poursuite de la lecture des données
    if(req->requestType > -1)  {
    	ret = recv(socket, (void*)req->data1, sizeOf(req.data1), 0);
    	if(req->requestType > 0)  {
    		ret = recv(socket, (void*)req.data2, sizeOf(req.data2) * 20, 0);
    	}
    	//etc.
    }
    Pensez-vous que ce principe puisse fonctionner ? (a priori je dirais que non)
    Merci d'avance.
    (Je vais essayer de mon côté mais je n'ai pas de compilateur sous la main.

  2. #2
    Membre émérite Avatar de orfix
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 707
    Par défaut
    Les éléments de la structure seront adjacents, mais pour des soucis d'alignement il se pourrait qu'il y ai des trous entre ces derniers ainsi qu'à la fin de la structure, auquel cas ceci ne fonctionnerais pas :
    Code Djakisback : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    request req;
    //...
    // Type 0, envoi de requestType et data1 uniquement (2 int)
    ret = send(socket, (void*)&req, sizeof(int) * 2, 0);
     
    // Type 1, envoi de requestType, data1 et data 2
    ret = send(socket, (void*)&req, sizeof(int) * 2 + sizeof(char) * 20, 0);
    moi je procéderais en plusieurs temps comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    send(socket, &req.requestType, sizeof req.requestType, 0);
    send(socket, &req.data1, sizeof req.data1, 0);
    /* ...et ainsi de suite */

  3. #3
    Membre Expert Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Par défaut
    Salut et merci pour ta réponse

    Citation Envoyé par ssmario2 Voir le message
    Les éléments de la structure seront adjacents, mais pour des soucis d'alignement il se pourrait qu'il y ai des trous entre les derniers ainsi qu'à la fin de la structure, auquel cas ceci ne fonctionnerais pas
    Effectivement je m'attendais à un truc du style ^^
    Oui, donc si je fais l'envoi en plusieurs fois ça fonctionnera mais dans ce cas la structure n'a d'intérêt que pour le stockage local des données, dommage je trouvais l'idée sympa.

    En gros de ce que je comprends, on a le choix entre :
    - avoir plusieurs structures pour différents type de requêtes et complexifier le code serveur/client
    - utiliser une structure de requête générique. Donc avoir du code simplifié mais envoyer des octets inutiles car non initialisés

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

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par Djakisback Voir le message
    Oui, donc si je fais l'envoi en plusieurs fois ça fonctionnera mais dans ce cas la structure n'a d'intérêt que pour le stockage local des données, dommage je trouvais l'idée sympa.
    En fait, tu peux avoir deux parties plus ou moins distinctes pour ta structure : la partie "commune", déterminant notamment le type de requête, et la partie variable (dont la taille reste à définir par protocole et/ou par un champ de taille dans la requête elle-même). Pour émettre la partie commune (et surtout, en avoir la taille), il te suffit de faire la différence entre l'adresse du premier champ variable et l'adresse du début de la structure : ce sera constant sur la vie du programme, donc à voir si tu initialises une globale avec cette valeur (si c'est calculé systématiquement) ou si l'optimisation permet de le faire via un #define.

    En ce cas, tu effectues seulement deux envois quel que soit la requête : le premier inconditionnellement, le second au sein d'un switch conditionné par l'identifiant de requête. Par contre, cela impose de connaître et de figer l'alignement de ta structure, ainsi que les tailles des données et l'endianness afin de garantir une communication fiable entre le client et le serveur. A titre de simplification, tu peux bien sûr décider d'utiliser du little-endian, mais habituellement, en réseau, c'est plutôt du big-endian que l'on utilise.

    Citation Envoyé par Djakisback Voir le message
    En gros de ce que je comprends, on a le choix entre :
    - avoir plusieurs structures pour différents type de requêtes et complexifier le code serveur/client
    - utiliser une structure de requête générique. Donc avoir du code simplifié mais envoyer des octets inutiles car non initialisés
    Non, une seule structure contenant :
    • Un entête commun à toutes les requêtes (sous-structure ou envoi partiel),
    • Une union de N éléments variables en fonction de la requête définie dans l'entête.


    Dans tous les cas, ne pas figer l'alignement, la taille des données et l'endianness lors d'une communication réseau binaire, c'est plutôt casse-gueule...
    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. #5
    Membre Expert Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Par défaut
    Merci pour ces précisions
    Mais à vrai dire je ne comprends pas bien, est-ce que tu aurais un exemple rapide ?
    Car j'ai l'impression que d'après ce que tu dis, ce que je proposais dans mon premier exemple fonctionnerait ? Tu proposes bien d'envoyer la structure en 2 temps ? Mais le problème soulevé par ssmario2 reste le même non ?

    [edit]En réalité, tu proposes d'envoyer une union de N éléments variables en fonction de la requête définie dans l'entête.[/edit] Donc si je comprends bien tu proposes d'envoyer toujours la même taille de données ?

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

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par Djakisback Voir le message
    Donc si je comprends bien tu proposes d'envoyer toujours la même taille de données ?
    La taille de l'union est certes la taille de la plus grande de ses alternatives... Mais qui a dit que tu étais obligé d'envoyer le sizeof(union), en lieu et place du sizeof() spécifique associé à la requête ?

    En gros (cf. points en rouge) :
    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
    typedef struct {
      struct header {
        int request_type ;
        int data1 ;
        char common_data[XXX] ;
        .....
      } h ;
      union data {
        struct data_r1 {
          char xxxx ;
        } d1 ;
        struct data_r2 {
          char yyyy[10000] ;
          float zzzz ;
        } d2 ;
        ......
      } d ;
    } request ;
    
    
    int send_request ( int socket, request* req ) {
    
      int ret ;
    
      ret = send(socket,&(req->h),sizeof(req->h),0);
      if (ret==0)
        switch (req->h.request_type) {
          case REQUEST1 :
            ret = send(socket,&(req->d.d1),sizeof(req->d.d1),0);
            break ;
    
          case REQUEST2 :
            ret = send(socket,&(req->d.d2),sizeof(req->d.d2),0);
            break ;
    
          default :
            ret = -1 ;
            break ;
        }
        return ret ;
    }
    C'est plus clair ?
    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

+ Répondre à la discussion
Cette discussion est résolue.

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