xilebo noone | Salut,
Bon, apparemment, je n'ai pas du bien comprendre comment fonctionne UDP, je rencontre quelques soucis pour transférer des datas via ce protocole.
Je souhaite envoyer des paquets XML en broadcast sur le réseau, et ceux-ci sont de taille variable (meme si j'arrive a garantir qu'ils sont plus petit qu'une trame).
Je procède donc de la façon suivante :
Code :
- int data = 0;
- int recu = 0;
- fd_set fdin;
- timeval tv;
- char entete[12];
- FD_ZERO(&fdin);
- FD_SET(m_socket, &fdin);
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- data = select(((int)m_socket)+1, &fdin, NULL, NULL, &tv);
- if (data == -1)
- {
- PAP_ERROR("Erreur select : %s",strerror_socket(errno));
- return -1;
- }
- else if (FD_ISSET(m_socket, &fdin) != 0)
- {
- socklen_t nSaiLen = sizeof(struct sockaddr_in);
- recu = recvfrom(m_socket, entete, 12, 0, (struct sockaddr*)emetteur, &nSaiLen);
- BYTE *pointeur = (BYTE *)entete;
- ULONG magic = GET_RAW_DWORD(pointeur);
- ULONG len = GET_RAW_DWORD(pointeur);
- ULONG chk = GET_RAW_DWORD(pointeur);
- if (recu == 12)
- {
- PAP_TRACE("recu = 12" );
- if (magic == MAGIC_NUMBER)
- {
- PAP_TRACE("Magic Number OK" );
- if (buffer == NULL)
- {
- buffer = malloc(len + 1);
- recu = recvfrom(m_socket, buffer, len, 0, (struct sockaddr*)emetteur, &nSaiLen);
- PAP_TRACE("retour 2eme recvfrom %d",recu);
- buffer[len] = 0;
- if (recu == len)
- {
- if (chk == getStringCRC(buffer+12,len) )
- {
- return len;
- }
- }
- else if (recu < len && recu > 0)
- {
- free (buffer);
- buffer = NULL;
- PAP_ERROR("Lecture data insuffisante %d",recu);
- return -1;
- }
- else if (recu == 0)
- {
- // lu 0 octets, erreur réseau
- free( buffer);
- buffer = NULL;
- PAP_ERROR("Lu data 0 octets. errno = : %s ??",strerror_socket(errno));
- return -1;
- }
- else
- {
- free( buffer);
- buffer = NULL;
- PAP_ERROR("Erreur de lecture data. errno = : %s ??",strerror_socket(errno));
- return -1;
- }
- }
- else
- {
- PAP_ERROR("Buffer non NULL, ne peut pas allouer" );
- }
- }
- }
- else if (recu <12 && recu > 0 )
- {
- PAP_ERROR("Lecture insuffisante %d",recu);
- return -1;
- }
- else if (recu == 0)
- {
- // lu 0 octets, erreur réseau
- PAP_ERROR("Lu 0 octets. errno = : %s ??",strerror_socket(errno));
- return -1;
- }
- else // recu < 0
- {
- // erreur de lecture
- PAP_ERROR("Erreur de lecture. errno = : %s ??",strerror_socket(errno));
- return -1;
- }
- }
- else
- {
- // aucune donnée recue dans les 1000 ms.
- #if (PAP_NIVEAU_TRACE>=3)
- PAP_TRACE("Aucune donnée reçue." );
- #endif
- return 0;
- }
|
Mon emetteur envoie 160 octets : entete de 12 octets + 148 datas.
Si je fais comme ci dessus : select + lecture 12 octets + lecture du restant, le 2eme recvfrom me retourne une erreur : ressource temporary unavailable.
Si je mets un select entre les 2, le 2eme select ne voit pas de data , je ne peux donc pas lire les 148 restants.
Pire que ca, ma fonction étant rappelée plus tard, elle relit 12 octets, et trouve bien l'entete de ma trame suivante. Cela signifie que mes 148 octets sont tout simplement perdus.
Si par contre je lis 160 octets d'un coup (select + recvfrom de 160 octets), pas de pb, je récupère la totalité.
Cela signifierait donc que UDP ne permet pas de lire une trame (un DATAGRAM) en plusieurs fois ? Dans ce cas, très difficile d'utiliser UDP avec des paquets de taille variable , et je comprends pourquoi dans la doc il est écrit qu'UDP est plus adapté à un protocole avec des paquets de taille fixe.
Quelqu'un peut me confirmer ? Ou m'éclairer sur des points que je n'aurais pas compris ?
merci  |