J'utilise des sockets c pour implémenter un protocole UDP fiable. J'utilise le code suivant pour définir un délai d'expiration sur un socket dans lequel j'attends un accusé de réception. Je ne sais pas pourquoi j'obtiens errno 11, ressource temporairement indisponible.
//set timer for recv_socket
struct timeval tv;
tv.tv_usec = TIMEOUT_MS;
if(setsockopt(rcv_sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) < 0){
printf("Error setting the socket timeout.\n");
}
int recv_msg_len;
if(recv_msg_len = recvfrom(rcv_sock, ackBuffer,sizeof(ackBuffer), 0,
(struct sockaddr *) &servAddr2, &fromSize) < 0){
//timeout reached
printf("Error Reporting: %d : %s\n", errno, strerror(errno));
num_timeouts++;
}
J'ai également essayé la méthode select mentionnée dans les commentaires. J'ai le code suivant dans une boucle, mais le recvfrom n'expire jamais.
fd_set set;
FD_ZERO(&set); /* empties the set */
FD_CLR(rcv_sock,&set); /* removes FD from the set */
FD_SET(rcv_sock,&set); /* adds FD to the set */
if(select(rcv_sock + 1, &set, NULL, NULL, &tv) < 0){
printf("\nError Reporting: %d : %s\n\n", errno, strerror(errno));
return -1;
}
if(!FD_ISSET(rcv_sock,&set)){ /* true if FD is in the set */
printf("socket is not set properly.\n");
}
Lors de l'appel de recvfrom()
sur une socket bloquante et un délai d'expiration a été défini à l'aide de setsockopt()
il est normal d'obtenir l'erreur EAGAIN (11)
au cas où l'appel à recvfrom()
expiration (c'est-à-dire qu'aucune donnée n'a été reçue dans le délai spécifié comme expiration).
Verbatim de man recvfrom
:
VALEUR RENVOYÉE
...
ERREURS
...
EAGAIN ou EWOULDBLOCK Le socket est marqué comme non bloquant et l'opération de réception se bloquerait ou un délai de réception a été défini et le délai a expiré avant la réception des données . ...
Pour contourner cela: appelez simplement recvfrom ()
à nouveau ... ;-)
Pour moi, le problème était dû à l'arrivée de paquets ipV6 sur un socket UDP lié à un port particulier. Celles-ci déclenchaient le select () mais quand j'ai essayé de les lire en utilisant recvfrom () l'appel a renvoyé "Ressource temporairement indisponible". Je n'ai pas besoin d'IPV6 pour mon application, je l'ai donc simplement désactivé via sysctl.conf. Le problème a maintenant disparu!