Soutenez-nous
Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 2 sur 2
  1. #1
    Invité de passage
    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 : 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;
    }

  2. #2
    Membre à l'essai
    Inscrit en
    octobre 2004
    Messages
    57
    Détails du profil
    Informations forums :
    Inscription : octobre 2004
    Messages : 57
    Points : 20
    Points
    20

    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 ).

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
  •