2010-11-01 5 views
1

J'utilise l'option SO_REUSEADDR, mais je ne suis pas sûr de savoir pourquoi j'obtiens Option non disponible temporaire de ressource.SO_REUSEADDR avec datagrammes UDP - Ressource indisponible

Je teste le code du serveur client sur 127.0.0.1

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
{ 
    perror("socket() error!!\n"); 
    exit(1); 
} 

if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { 
    perror("SO_REUSEADDR failed::"); 
    exit(1); 
} 

while(1) { 

    nbytes_read = recvfrom(sockfd, (void *)&recvd_msg, sizeof(recvd_msg), 
          flags, &from, &from_len); 
    printf("nbytes_read = %d\n", nbytes_read); 
    if(nbytes_read == -1) { 
     perror("client: recvfrom() failed"); 
     return FAILED; 
    } 
    if (nbytes_read > 0) { 
     if(recvd_msg.hdr.msgtype == DATA) 
      printf("recvd %d bytes from server\n", recvd_msg.hdr.payload_size); 
      ftp_show_payload(&recvd_msg); 
    } 
    if(recvd_msg.hdr.is_last == TRUE) { 
     break; 
    } 
} 

Message d'erreur: "client: recvfrom() a échoué: Ressource temporairement indisponible"

errno: 11

Après essayer d'exécuter le client pour 3-4 fois, je reçois les données, je ne suis pas sûr de ce qui se passe.

En outre, ce problème est sur Ubuntu Linux, mais quand je lance le même serveur client sur Solaris, ça marche bien !!

+0

Vous n'avez pas besoin de l'étiquette ou du goto. Utilisez continuer. Et vous pouvez seulement obtenir zéro en mode non-bloquant, auquel cas vous devriez sélectionner(), pas seulement tourner. Et vous n'avez pas besoin de 'else' après 'return'. – EJP

+0

ok, j'ai changé tout ce que vous avez dit, mais je ne sais toujours pas pourquoi je reçois EAGAIN (ressource indisponible) .. – Anonymous

+0

Non, vous n'avez pas. Si vous obtenez EAGAIN, vous devez être en mode non bloquant, vous devez donc appeler select() pour vous indiquer quand les données sont disponibles. – EJP

Répondre

0
  1. Votre test n'est pas valide. recvfrom() peut renvoyer zéro, ce qui n'indique pas une erreur. Il est seulement valide d'appeler perror() si vous obtenez -1. Donc, vous ne pouvez pas avoir un problème du tout ..

  2. Je ne vois pas pourquoi vous utilisez SO_REUSEADDR du tout ici, car vous n'êtes pas lié à un port spécifique.

0

Etes-vous en train de supprimer toute autre configuration de socket? EAGAIN est généralement renvoyé lorsque vous lisez un socket non bloquant et qu'aucune donnée n'est disponible. La page de manuel recvfrom répertorie les errnos possibles qui seront définis en cas d'échec avec une explication pour chacun d'eux.

+0

je reçois errno: 11 Resource temporairement indisponible – Anonymous

+0

C'est le "joli" nom pour EAGAIN (aka EWOULDBLOCK). Vous pouvez le vérifier en imprimant 'strerror (EAGAIN)'. Malheureusement, je sais aussi que EAGAIN est également ... –

+0

mais pourquoi devrais-je obtenir EAGAIN, mon serveur de fichiers udp, m'envoie beaucoup de données, et parfois je le vois, et parfois je vois EAGAIN, quelle pourrait être la raison – Anonymous

1

SO_REUSEADDR est utile lorsque vous utilisez bind(), mais ici, vous n'utilisez pas de liaison.

Je ne vois aucun problème si recvfrom() retours -1

Utilisez bind() et remplacer votre appel recvfrom() avec recv(). recv() recevra tous les paquets au port que vous avez utilisé dans votre appel de liaison.

Questions connexes