Bonjour à tous,
J'ai fait une fonction qui gère des entrées formattées sur un socket UDP à la scanf, qui ne marche plus :( En fait, il y a une fonction qui gère l'interpretation du formattage, et qui appelle au fur et a mesure la fonction buggée pour lire ce dont elle a besoin. Je me suis aperçu que ça ne marchait jusqu'il y a peu que parce que j'envoyais mes structures champ par champ et non pas entièrement linéarisées (vieux bug qui s'était fait discret, le bougre).
Depuis, je me bat avec recvfrom qui apparamment passe à la requête suivante dès que je l'appelle.
Exemple :
J'envoie une structure contenant un long (4 octets), un short, un long, et une chaine de 25 chars. Je swappe et je linéarise, et ça me fait 36 chars à envoyer d'un coup, alors qu'avec mon algo précédent j'aurais eu 4 requètes séparées.
Problème :
De l'autre coté, je récupère mon long en faisant un recvfrom (un vrai, avec flag 0) sur 4 octets, puis mon short avec 2 octets, et encore 4 octets pour le dernier long. Déjà, premier bug, à chaque fois je récupère les n premiers octets d'une nouvelle requête complète :(
Ensuite, pour la chaîne, c'est encore plus amusant car je ne connais pas la longueur à l'avance. Je lis donc avec le flag MSG_SEEK pour ne pas enlever les données du buffer jusqu'à ce que je rencontre un NULL ou que recvfrom plante. Mais comme je suis mal positionné, je ne récupère jamais ma chaîne... :'(
Solutions envisagées :
* Un buffer et un indice conservés par la fonction appelante et passés par adresse ? (pas de static, mon programme est theadé)
* Aller me coucher car il est bien tard (3:39 argh !)
Là je ne sais plus trop quoi faire, alors que me suggérez vous ?
# mauvaise methode
Posté par kesako . Évalué à 3.
et ensuite :
> je ne connais pas la longueur à l'avance.
????
si tu connais la longueur , met la en tete du message et boucle sur un select ou un poll jusqu'a avoir recu l'integralité de cette longueur (avec un timeout pour se proteger)
[^] # Re: mauvaise methode
Posté par kesako . Évalué à 4.
j'ai lu trop vite. pas vu que c'etait de l'UDP.
Ce que je conseillais c'est bon pour le TCP seulement.
Pour l'UDP , comme l'indique justement SoWhat , il faut tout recuperer d'un coup sinon c'est perdu. Donc un gros buffer de 64k avec un seul recvfrom et ensuite on traite la reponse.
# Trop compliqué ton truc
Posté par forc3 . Évalué à 3.
max possible ?
Après tu le parcours tout simplement...
[^] # Re: Trop compliqué ton truc
Posté par SoWhat . Évalué à 3.
L'avantage qu'on peut y voir, c'est que si l'emetteur fait un 'sendto' de 36 octets, on est _sûr_ que le datagramme reçu par l'autre bord aurra lui aussi une taille de 36 octets. Comme on ne connait aps forcément la taille avant le lecture, on utilise souvent un buffer de 65536 octets comme paramètre de l'appel à 'recvfrom', puis on recopie les données effectivement reçues dans un buffer de taille plus appropriée (si besoin).
[^] # Re: Trop compliqué ton truc
Posté par forc3 . Évalué à 1.
Un buffer de 1500 suffit amplement pour un recvfrom ...
# Longueurs des données ...
Posté par Obsidian . Évalué à 3.
Ensuite, il se peut que gcc (au fait, tu développes bien en C ?) fasse des optimisations, comme par exemple stocker un char ou un short sur un entier 32 bits pour faire des alignements en mémoire. Dans ce cas, tu risques d'envoyer du padding à travers le socket et de recevoir une structure imcomplète. Vérifie si c'est le cas à l'aide d'un sizeof(TaStructure), et en examinant les adresses de chacun de tes champs par rapport à celle de la structure elle-même.
Bon courage.
# Merci beaucoup
Posté par JaguarWan . Évalué à 2.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.