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 :

appel intempestif à recv


Sujet :

Réseau C

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Février 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Février 2008
    Messages : 9
    Points : 6
    Points
    6
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : 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
     
    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 : 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
     
    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;
    }

  2. #2
    Membre du Club
    Inscrit en
    Octobre 2004
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Octobre 2004
    Messages : 59
    Points : 49
    Points
    49
    Par défaut
    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 ).

Discussions similaires

  1. [Performances] Appels répétés de 'recv()'
    Par Latoof dans le forum Réseau
    Réponses: 3
    Dernier message: 11/01/2013, 15h41
  2. Appels intempestifs de fesetenv, fesetround et feholdexcept
    Par flavien tetart dans le forum Fortran
    Réponses: 4
    Dernier message: 30/11/2009, 12h32
  3. Réponses: 5
    Dernier message: 10/07/2009, 22h43
  4. [socket] appel de recv() depuis le client
    Par Tymk dans le forum C++
    Réponses: 22
    Dernier message: 02/08/2008, 19h19
  5. appel de fichier d'Aide
    Par Atrebate62 dans le forum Composants VCL
    Réponses: 5
    Dernier message: 24/09/2002, 14h13

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