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 :

Send() une matrice de structure en SOCKET


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 18
    Points : 10
    Points
    10
    Par défaut Send() une matrice de structure en SOCKET
    Bonjour

    J'essaie de connaitre la taille de ma matrice de structure pour l'envoyer, seulement, je ne recois pas toute les données.

    Voici les éléments :

    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
    Mon prototype de structure :
     
    typedef enum {Vide, Ver, Plante} te_Nourriture;
    typedef enum {Rien, Petit, Moyen, Plein, Pierre} te_Etatterre;
    typedef struct {te_Nourriture Nourriture; int ptNourriture; te_Etatterre eEtatterre; int eTaupes;} t_motte;
     
    Mon allocation de ma structure est celle ci :
     
    	t_motte** pMotte;
    	// allocation mémoire pour le tableau de sous-tableaux :
    	pMotte = (t_motte**) malloc(elmax * sizeof(t_motte*));
     
    	// allocation mémoire pour chaque sous-tableau de de structure :
    	for (eLigne = 0; eLigne < elmax; eLigne++)
    		pMotte[eLigne] = (t_motte*) malloc(ecmax * sizeof(t_motte));
     
    Jusque là pas de soucis et mon envoi :
     
    	for(eLigne=0;eLigne<elmax;eLigne++)
    		send(csock[eNombreJoueurIncremente], pMotte[eLigne], ecmax*sizeof(pMotte), 0);
     
    Ma réception :
     
    	for (eLigne = 0; eLigne < elmax; eLigne++)
    		recv(csock[eNombreJoueurIncremente], pMotte[eLigne], ecmax*sizeof(pMotte), 0);
    Merci d'avance

  2. #2
    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
    send() et recv() retournent le nombre d'octets envoyés/reçus. Il peut être nécessaire d'appeler recv() en boucle.
    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.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    C'est pas déjà ce que j'ai fait ?

  4. #4
    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
    Pas correctement. Tu dois calculer la taille totale de ton envoi, et appeler recv() en boucle en comptant les tailles reçues jusqu'à tout avoir reçu.
    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.

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

    Informations forums :
    Inscription : Novembre 2012
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Hummm je vois pas très bien comment procéder :/
    Pour moi j'avais fait un code correct avec ce que j'avais lu

  6. #6
    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
    Ce qu'il faut savoir, c'est que recv() peut recevoir moins que la taille que tu lui passes en paramètre.

    PS: Pour ton tableau 2D, si ses dimensions sont fixes, je te conseille de l'allouer avec une telle fontion à la place: Comme ça, tu auras un tableau d'un seul tenant dont tu pourras te servir comme d'un seul buffer pour tes appels à recv() en boucle.
    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.

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Si j'ai bien comprit.
    Je passe ma matrice de structure(en pointeur) en statique dans un tableau a 2 dimensions. J'envoie mon tableau, je recois le tableau a 2 dimensions et je le remet dans ma matrice de structure en pointeur c'est ca ?

    Edit : J'ai vu qu'il fallait faire de la serialisation de donnée.
    En gros il faudrait que j'envoie chacune des valeurs de ma structure une par une pour chacune des dimensions ?

  8. #8
    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
    Je n'ai jamais parlé de tableau à deux dimensions statique. J'ai seulement parlé de tableau à deux dimensions d'un seul bloc, avec une allocation par dimension au lieu de N+1 allocations.

    Ensuite, tes structures n'ont pas vraiment besoin d'être sérialisées vue leur simplicité. Et même s'il fallait les sérialiser, il serait mieux de les sérialiser vers un buffer mémoire que tu enverrais ensuite avec les mêmes considérations de boucle que j'ai déjà soulevées.
    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. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Oui mais du coup avec ta fonction, ca va me faire changer tout le code ?
    Du moins j'ai essayé avec ton code de l'adapté à l'initialisation de ma matrice, compilation ok mais lors de l'exécution ca ne fonctionne pas.
    Surtout que si la taille de ma matrice est variable ton système ne serait pas approprié ?

    Tu aurais un exemple d'envoi de structure à plusieurs dimensions ? ^^
    Pour l'instant je pense qu'à mon niveau la sérialisation serait plus approprié :
    J'envoie en gros tout mes entiers un par un, je met un symbole comme séparation de ligne, un symbole comme séparation de colonne ainsi qu'un symbole de séparation pour définir la fin de mon envoi et voilà

  10. #10
    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
    Normalement, si les dimensions de ton tableau 2D ne changent pas une fois alloué, changer la fonction d'allocation ne t'obligera pas à changer grand-chose (juste l'allocation et la suppression, et le redimensionnement s'il y en a).
    Par contre, cela permettra de changer le code d'envoi/réception plus facilement vu que la matrice de structures sera continue.

    Si tu sérialises, évite d'envoyer tout un par un, c'est désastreux pour les performances. Si tu sérialises, ce doit donc être vers un buffer. Mais vu que tes structures ne contiennent que des entiers, si tu mets tout dans un tableau continu, tu n'auras pas besoin de sérialiser.

    Normalement, pour le code d'allocation, tu as juste à remplacer double par t_motte, puis passer elmax et ecmax en paramètre de la fonction.

    Ensuite, l'accès aux structures individuelles se fait de la même façon qu'avant, puisque tu as toujours un tableau de pointeurs sur des tableaux.
    Et si tu veux envoyer tout, il te suffit d'envoyer &(pMotte[0][0]) avec comme taille ecmax*elmax*sizeof(t_motte). Ceci n'est possible que si tu utilises la fonction pour que ton tableau soit continu.
    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. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Très bien je vais réessayer ça.
    En tout cas, merci de m'aider

    J'avais fait ca en sérialisation :
    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
    	for(eLigne=0;eLigne<elmax;eLigne++){
    		for(eColonne=0;eColonne<ecmax;eColonne++){
    			eDonnee=pMotte[eLigne][eColonne].Nourriture;
    			send(csock[eSocketincremente], &eDonnee, sizeof(eDonnee), MSG_NOSIGNAL);
    			eDonnee=pMotte[eLigne][eColonne].ptNourriture;
    			send(csock[eSocketincremente], &eDonnee, sizeof(eDonnee), MSG_NOSIGNAL);
    			eDonnee=pMotte[eLigne][eColonne].eEtatterre;
    			send(csock[eSocketincremente], &eDonnee, sizeof(eDonnee), MSG_NOSIGNAL);
    			eDonnee=pMotte[eLigne][eColonne].eTaupes;
    			send(csock[eSocketincremente], &eDonnee, sizeof(eDonnee), MSG_NOSIGNAL);
    			cSeparateur="#";
    			send(csock[eSocketincremente], &cSeparateur, sizeof(eDonnee), MSG_NOSIGNAL);		
    		}
    	cSeparateur="@";
    	send(csock[eSocketincremente], &cSeparateur, sizeof(eDonnee), MSG_NOSIGNAL);
    	}
    mais c'est vrai qu'avec un buffer ca éviterait d'envoyer tout un par un. Par contre il faudrait garder les séparateurs je pense.

    Edit, bon la compilation et l'exécution sont passé, j'ai enlevé un de mes asserts, cependant à l'affichage, j'ai des données non cohérentes

    Plus quelque chose comme ca pour la sérialisation ?

    Serveur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    	int eLigne; int eColonne;
    	int eDonnee[4];
    	char cSeparateur;
     
    	for(eLigne=0;eLigne<elmax;eLigne++){
    		for(eColonne=0;eColonne<ecmax;eColonne++){
    			eDonnee[0]=pMotte[eLigne][eColonne].Nourriture;
    			eDonnee[1]=pMotte[eLigne][eColonne].ptNourriture;
    			eDonnee[2]=pMotte[eLigne][eColonne].eEtatterre;
    			eDonnee[3]=pMotte[eLigne][eColonne].eTaupes;
    			send(csock[eNombreJoueurIncremente], (char *)eDonnee, sizeof(eDonnee), MSG_NOSIGNAL);
    		}
    	}
    Client :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    	int eLigne; int eColonne;
    	int eDonnee[4];
    	char cSeparateur;
    	for(eLigne=0;eLigne<elmax;eLigne++){
    		for(eColonne=0;eColonne<ecmax;eColonne++){
    			recv(csock, (char *)eDonnee, sizeof(eDonnee), MSG_NOSIGNAL);
    			pMotte[eLigne][eColonne].Nourriture=eDonnee[0];
    			pMotte[eLigne][eColonne].ptNourriture=eDonnee[1];
    			pMotte[eLigne][eColonne].eEtatterre=eDonnee[2];
    			pMotte[eLigne][eColonne].eTaupes=eDonnee[3];		
    		}
    	}
    Mais j'obtiens une erreur de segmentation à partir d'un certain nombre de boucle recu chez le client :/

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Bon au final, ayant un peu réfléchi, chaque élément contient 4 entiers (de taille 4octets) donc 4*4 = 16 octets. J'envoie une ligne entière de cmax colonne donc j'ai la taille avec cmax*16 et j'ai toute ma matrice.
    C'est correct ?

  13. #13
    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
    Déjà la taille ce sera cmax*sizeof(t_motte) et non pas cmax*16, ensuite souviens-toi de ce que j'ai dit sur les considérations de taille.
    Citation Envoyé par [url=http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121%28v=vs.85%29.aspx]recv function[/url]
    For connection-oriented sockets (type SOCK_STREAM for example), calling recv will return as much data as is currently available—up to the size of the buffer specified.
    En fait, pour la réception, il te faudrait plutôt un truc de ce genre, pour être sûr de tout choper:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /*Retourne totalReceived si OK, 0 si déconnexion ou une valeur négative si erreur.
    Remplit toujours *pTotalReceived.*/
    int recv2(int sock, void* buf, int len, int flags, int *pTotalReceived)
    {
    	int totalReceived = 0;
    	int received = 0;
    	while((received=recv(sock, buf+totalReceived, len-totalReceived, flags)) > 0)
    		totalReceived += received;
    	*pTotalReceived = totalReceived;
    	return (received >= 0 ? totalReceived : received)
    }
    Et si tu utilises ma fonction AutreAllocTable2D pour créer ta matrice, tu peux même l'envoyer d'un bloc et non pas ligne par ligne. Mais seulement si tu l'utilises.
    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.

  14. #14
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 18
    Points : 10
    Points
    10
    Par défaut
    Bon au final tout marche impeccable avec les tailles que tu m'as dis, j'arrive à envoyer et recevoir les données entre client serveur.

    Il me reste à jeter un coup d’œil sur les threads pour terminer la connexion client si le serveur ferme la connexion parce que un while(1) c'est pas top

    Merci pour ton aide en tout cas de m'avoir éclairer sur les tailles d'envoi et de réception : je verrais ca qu'en L3 mais bon, c'est histoire d'avoir une bonne note en projet !

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

Discussions similaires

  1. utilisé deux structures pour une matrice
    Par simplyc dans le forum Débuter
    Réponses: 3
    Dernier message: 01/12/2010, 14h05
  2. Envoi d'une structure via sockets
    Par milanoran dans le forum C++
    Réponses: 8
    Dernier message: 17/11/2010, 14h19
  3. Envoi d'une matrice sur socket UDP
    Par caubios dans le forum Qt
    Réponses: 0
    Dernier message: 10/02/2010, 19h10
  4. [Structure] Stockage d'une matrice en XML
    Par mamid1706 dans le forum XML/XSL et SOAP
    Réponses: 6
    Dernier message: 15/03/2007, 16h14
  5. Afficher les valeurs d'une structure dans une matrice
    Par yabbiyou dans le forum MATLAB
    Réponses: 1
    Dernier message: 22/02/2007, 12h26

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