2011-04-20 4 views
4

J'ai un problème avec sendto.sendto: Ressource temporairement indisponible (errno 11)

J'ai un récepteur qui reçoit des paquets UPD avec recvfrom puis répond à l'expéditeur en utilisant sendto.

Malheureusement, je reçois errno 11 (ressource momentanément indisponible). J'utilise deux prises.

Le premier paquet est effectivement envoyé, mais pas ceux après:

sendto :: Succès

erreur: 0.

sendto :: ressource temporairement indisponible

erreur: 11.

sendto :: Ressource temporairement indisponible

...

Ceci est un extrait de mon code:

int sockfd, sockSend; 

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
      perror("socket"); 

    if ((sockSend = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
      perror("socket"); 

    if (fcntl(sockfd, F_SETOWN, getpid()) < 0) { 
      perror("fcntl"); 
    } 
    if (fcntl(sockfd, F_SETFL, O_RDONLY | O_NONBLOCK | FASYNC) < 0) { 
      perror("fcntl"); 
    } 

    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) 
        < 0) 
      perror("bind"); 

Et dans un gestionnaire SIGIO:

len = sizeof(recv_addr); 
    char buffer[payload]; 
    bzero(buffer, payload); 
    n = recvfrom(sockfd, buffer, payload, MSG_DONTWAIT, (struct sockaddr *)&recv_addr, &len); 

    while (n > 0) { 

          sprintf(response, "%d\n%d\n%d\n", items, target_buf, pb_sp);   
          sendto(sockSend, response, strlen(response), 0, (struct sockaddr *) &recv_addr, sizeof(recv_addr)); 
          // sleep(1); 

          perror("sendto :"); 
          printf("error: %d.\n", errno); 

    } 

cette question pourrait venir parce que le port est encore chaud, et je besoin d'attendre avant de le réutiliser? J'ai essayé de changer de port mais ça n'a pas aidé.

Mise à jour: Si le sommeil (1) est commenté, les paquets se fait envoyer!

Merci beaucoup pour votre aide.

+0

Utilisez-vous deux prises avec le même port? Si oui, quelle est la raison? – penguin359

+0

Peut-être 'SO_REUSEADDR' aiderait. Ou vous pouvez simplement garder le port ouvert plutôt que de l'ouvrir et de le fermer, ou utiliser un nouveau numéro de port assigné au hasard à chaque fois si c'est faisable. –

+0

J'ai ajouté plus de code. J'ai 2 sockets mais un seul est lié à un port (pour recevoir des données sur un port spécifique), l'autre peut envoyer des données à partir de n'importe quel port. – Jary

Répondre

8

L'erreur que vous obtenez:

EAGAIN or EWOULDBLOCK: The socket is marked nonblocking and the requested operation would block. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities.

Vous définissez la prise de non-blocage (O_NONBLOCK). Le socket est toujours occupé à envoyer le message précédent. Vous ne pouvez pas en envoyer un autre tant que le premier n'a pas été envoyé. C'est pourquoi le sommeil a aidé.

Ne réglez pas à la non-blocage, ou essayez à nouveau après select dit que vous pouvez.

+0

Merci beaucoup. Mais O_NONBLOCK est pour sockfd, ne devrait pas sockSend bloquer (comportement par défaut)? J'utilise sockfd pour recevoir et sockSend pour envoyer des données. J'ai enlevé O_NONBLOCK dans fcntl() et le même comportement se produit.C'est ce que vous avez mentionné, n'est-ce pas? – Jary

+0

En supprimant O_NONBLOCK ET aussi MSG_DONTWAIT il finit par fonctionner! Merci beaucoup! Est-il possible de garder un socket bloquant (envoi) et un non bloquant (pour recevoir) s'il vous plaît?! – Jary

0

Si vous devez régler la prise de non-blocage, vous pouvez le faire en toute sécurité en utilisant select (et seulement?):

select() and pselect() allow a program to monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" for some class of I/O operation (e.g., input possible). A file descriptor is considered ready if it is possible to perform the corresponding I/O operation (e.g., read(2)) without blocking.

Questions connexes