Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 14 sur 14
  1. #1
    Invité de passage
    Inscrit en
    novembre 2012
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : novembre 2012
    Messages : 17
    Points : 4
    Points
    4

    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 :
    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 Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    24 126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 24 126
    Points : 35 202
    Points
    35 202

    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
    Invité de passage
    Inscrit en
    novembre 2012
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : novembre 2012
    Messages : 17
    Points : 4
    Points
    4

    Par défaut

    C'est pas déjà ce que j'ai fait ?

  4. #4
    Expert Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    24 126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 24 126
    Points : 35 202
    Points
    35 202

    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
    Invité de passage
    Inscrit en
    novembre 2012
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : novembre 2012
    Messages : 17
    Points : 4
    Points
    4

    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 Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    24 126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 24 126
    Points : 35 202
    Points
    35 202

    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
    Invité de passage
    Inscrit en
    novembre 2012
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : novembre 2012
    Messages : 17
    Points : 4
    Points
    4

    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 Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    24 126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 24 126
    Points : 35 202
    Points
    35 202

    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
    Invité de passage
    Inscrit en
    novembre 2012
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : novembre 2012
    Messages : 17
    Points : 4
    Points
    4

    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 Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    24 126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 24 126
    Points : 35 202
    Points
    35 202

    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
    Invité de passage
    Inscrit en
    novembre 2012
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : novembre 2012
    Messages : 17
    Points : 4
    Points
    4

    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 :
    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 :
    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 :
    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
    Invité de passage
    Inscrit en
    novembre 2012
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : novembre 2012
    Messages : 17
    Points : 4
    Points
    4

    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 Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    24 126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 24 126
    Points : 35 202
    Points
    35 202

    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 :
    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
    Invité de passage
    Inscrit en
    novembre 2012
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : novembre 2012
    Messages : 17
    Points : 4
    Points
    4

    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.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •