2012-11-25 8 views
11

Używam gniazd C do implementacji niezawodnego protokołu UDP. Korzystam z następującego kodu, aby ustawić limit czasu na gnieździe, w którym czekam na potwierdzenie. Nie wiem, dlaczego dostaję errno 11, zasób jest tymczasowo niedostępny.Errno: 11, Zasoby tymczasowo niedostępne

 //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++; 
     } 

Próbowałem również wybranej metody, która została wymieniona w komentarzach. Mam następujący kod w pętli, ale recvfrom nigdy nie wychodzi.

 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"); 
     } 
+0

Spróbuj użyć zamiast tego gniazd typu select() i nieblokujących. Metoda select() jest znacznie bardziej elastyczna, niezawodna i przenośna. –

+0

Nie ma żadnego połączenia z 'recvfrom()' int on second snippet. – alk

+0

'recvfrom()' zwraca 'ssize_t', a nie' int', BTW. – alk

Odpowiedz

13

Dzwoniąc recvfrom() na gnieździe blokowania i limit czasu został ustawiony za pomocą setsockopt() to jest normalne, aby uzyskać błędu EAGAIN (11) w przypadku wezwania do recvfrom() razy out (czyli: brak danych został odebrany w czasie okres określony jako limit czasu).

Verbatim z man recvfrom:

RETURN VALUE

...

BŁĘDY

... .

EAGAIN lub EWOULDBLOCK Gniazdo jest oznaczony nonblocking i operacja odbierania będzie blokować lub przekroczenie limitu czasu otrzymania została ustawiona, a czas oczekiwania upłynął zanim dane otrzymano. ...

Aby obejść ten problem: Wystarczy zadzwonić recvfrom() ponownie ... ;-)

+1

Niesamowita odpowiedź! Dziękuję Ci! – rharrison33

0

Dla mnie problem był spowodowany pakietów IPv6 przybywających na gniazda UDP związanego z danym porcie. Wywoływały one funkcję select(), ale kiedy próbowałem ją odczytać za pomocą funkcji recvfrom(), połączenie zwróciło "Zasób chwilowo niedostępny". Nie potrzebuję IPV6 dla mojej aplikacji, więc po prostu wyłączyłem go przez sysctl.conf. Problem teraz zniknął!