2012-11-25 32 views
11

Güvenilir bir UDP protokolü uygulamak için c soketleri kullanıyorum. Bir onay için beklediğim bir yuvada zaman aşımı ayarlamak için aşağıdaki kodu kullanıyorum. Neden errno 11 aldığımı bilmiyorum, kaynak geçici olarak kullanılamıyor.Errno: 11, Kaynak Geçici Olarak Kullanılamıyor

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

Ayrıca yorumlarda belirtilen seçme yöntemini denedim. Bir döngü içinde aşağıdaki kodlarım var, ama geri çekilme asla zaman aşımına uğruyor.

 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

Bunun yerine select() ve bloke olmayan soketleri kullanmayı deneyin. Select() yaklaşımı çok daha esnek, güvenilir ve taşınabilirdir. –

+0

Recvfrom() 'int ikinci snippet'e çağrı yok. – alk

+0

'recvfrom()' 'ssize_t'' int', BTW'yi döndürür. – alk

cevap

13

bir engelleme soket üzerinde recvfrom() ve dışarı olması durumunda bu takım recvfrom() kez çağrısı (yani hatayı EAGAIN (11) almak için normaldir setsockopt() kullanılarak belirlenmiş olduğunu bir defa çağırarak: hiçbir veri zamanla alındı zaman aşımı olarak belirtilen süre. man recvfrom den

Aynen:

DÖNÜŞ DEĞERİ

...

HATALAR

... .

EAGAIN veya EWOULDBLOCK soket beklememe işaretlenir ve alma işlemi bloke edecek veya alma zaman aşımı belirlenmiş olduğunu ve veri alındı ​​önce zaman aşımı süresi doldu. ...

Bundan kaçınmak için: Sadece tekrar recvfrom() diyoruz ... ;-) Benim için

+1

Awesome Answer! Teşekkür ederim! – rharrison33

0

, sorun belirli bir bağlantı noktasına bağlı bir UDP soket üzerinde gelen IPv6 paketlerini kaynaklanıyordu. Bunlar select() işlevini tetikliyordu, ancak recvfrom() yöntemini kullanarak okuyamaya çalıştığımda, çağrı "Kaynak geçici olarak kullanılamıyor" ifadesini döndürdü. Uygulamam için IPV6'ya ihtiyacım yok, bu yüzden sysctl.conf ile devre dışı bıraktım. Sorun şimdi gitti!

İlgili konular