Précédent   Forum du club des développeurs et IT Pro > C et C++ > C > Réseau
Réseau Forum d'entraide sur la programmation réseau en C
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 04/11/2012, 16h51   #1
Nico_FrancComtois
Invité de passage
 
Homme
Inscription : février 2008
Messages : 9
Détails du profil
Informations personnelles :
Sexe : Homme

Informations forums :
Inscription : février 2008
Messages : 9
Points : 1
Points : 1
Par défaut appel intempestif à recv

Bonjours la communauté.
En plein projet de crée mon propre serveur dns lié à postgres.
je m'amuse avec les socket udp.
tous marche comme prévue.
juste une question.
Ne puis-je pas faire appelle à deux fois d'affilé à la
fonction recvfrom.

Code :
n = recvfrom(*udp->sock, &octet, sizeof octet, 0, (SOCKADDR *)udp->dest, (socklen_t *)&udp->dest_size);
j'ai lut dans le man que udp->dest_size était une variable retour.
donc je n'oublie pas de réinitialiser.
aucune variable varie à part "octet" en vue pas à pas.

alors je ne comprend pas trop.
quand je fait un appelle avec un octet qui vaut :
tous fonctionne dans le meilleur des mondes.
je reçois mon bloque de centaines d'octet d'un coup.

mais ici je voudrais le faire fonctionner octet par octet.
histoire de pousser dans un buffer mes octet.
hors lors de mon deuxième appelle à recvfrom
pouf je n'ai plus rien.

enfin voici mon code final si cela interresse de ma fonction:
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
 
char darkdns_socket_udp_receive(Udp *udp,androBuffer *buffer)
{
 char octet;
 char bValid=0;
 int n=0;
 
 if (!udp || !buffer)
  fprintf(stderr,"darkdns_socket_udp_send no udp or no buffer");
 else {
  do {
   printf("go one octet\n");
   udp->dest_size=sizeof(*udp->dest);
   n = recvfrom(*udp->sock, &octet, sizeof octet, 0, (SOCKADDR *)udp->dest, (socklen_t *)&udp->dest_size);
   if (n>0) {
    buffer->write(buffer,&octet,n);
   }
  }while(n>0);
  if(n<0)
   fprintf(stderr,"recvfrom()");
  else
   bValid=1;
 }
 return bValid;
}
qui malheureusement ne fonctionne qu'ainsi :
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
 
char darkdns_socket_udp_receive(Udp *udp,androBuffer *buffer)
{
 char octet[1024];
 char bValid=0;
 int n=0;
 
 if (!udp || !buffer)
  fprintf(stderr,"darkdns_socket_udp_send no udp or no buffer");
 else {
  //do {
   //printf("go one octet\n");
   udp->dest_size=sizeof(*udp->dest);
   n = recvfrom(*udp->sock, &octet, sizeof octet, 0, (SOCKADDR *)udp->dest, (socklen_t *)&udp->dest_size);
   if (n>0) {
    buffer->write(buffer,&octet,n);
   }
  //}while(n>0);
  if(n<0)
   fprintf(stderr,"recvfrom()");
  else
   bValid=1;
 }
 return bValid;
}
Nico_FrancComtois est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/11/2012, 09h23   #2
xilebo
Membre à l'essai
 
Inscription : octobre 2004
Messages : 56
Détails du profil
Informations forums :
Inscription : octobre 2004
Messages : 56
Points : 20
Points : 20
Envoyer un message via ICQ à xilebo Envoyer un message via MSN à xilebo
C'est normal , en UDP tu es en mode DATAGRAM, ce qui signifie que tu ne peux recevoir le DATAGRAM envoyé qu'en une seule fois

Lorsque tu fais un recvfrom, il faut que tu sois en mesure de récupérer la totalité du paquet. Généralement, pour s'en assurer, on fait des paquets de taille fixe, ou de taille bornée.

Il faut imaginer que chaque appel recvfrom, c'est retirer non pas x octets de la pile , mais 1 paquet de la pile ( on dépile paquet par paquet ).

Ce que tu souhaites faire n'est possible qu'en TCP ( socket en mode STREAM ), où là, tu peux demander de lire octet par octet.


Ex : si ton application distante t'envoie 1 datagram de 1024 octets. Coté client, si tu fais un :
- recvfrom x < 1024 : tu ne recevras que x octets, et les 1024-x octets restants sont définitivements perdus
- recvfrom = 1024 : ok
- recvfrom y > 1024 : recvfrom te retournas 1024 octets lus

( tout ceci sous réserve que les buffers systèmes ne soient pas déja pleins ).


Une solution pour envoyer des DATAGRAM de taille variable mais bornée :

- entete fixe de x octets ( moi je fais 12 : 4 pour magic number , 4 pour longueur des datas , 4 pour checksum )
- data variable de taille bornée MAX ( ex 1012 octets ).

- tu fais un recv du max , dans mon exemple 1012+ 12 = 1024 octets

- recvfrom te retourne une valeur x inférieure ou égale = 1024, et tu testes que la longueur des datas de l'entête + 12 = valeur de retour de recvfrom ( le magic number est là pour t'assurer que c'est bien un paquet que tu attends, et le checksum pour vérifier l'intégrité des datas ).
xilebo est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 10h05.


 
 
 
 
Partenaires

Hébergement Web