2013-04-23 83 views
3

我按sendto發送一個UDP數據包,然後通過recv接收到答案,如果recv沒有收到答覆,程序不會繼續。但是,udp數據包可能會丟失,或者出於某種原因,數據包可能無法發送,因此程序卡在recv行。我想知道如果nopacket到達例如一分鐘後,如何設置recv的超時時間,然後跳過該行並繼續執行代碼?設置UDP套接字的recv fcn的超時時間

我不粘貼完整的代碼,因爲它是一個通用的udp代碼,我的問題與唯一的recv有關。最後一點,開發環境是linux。

unsigned long buf[maxlen]; 
struct protoent *proto;  // 
struct sockaddr_in server_addr; 
int s; // socket 
memset(&server_addr, 0, sizeof(server_addr)); 
server_addr.sin_family=AF_INET; 
server_addr.sin_addr.s_addr = inet_addr(hostname); 
sendto(s,msg,sizeof(msg),0,(struct sockaddr *)&server_addr,sizeof(server_addr)); 

recv(s,buf,sizeof(buf),0); 
+1

使插座非阻塞?或者使用例如用於輪詢的['select'](http://pubs.opengroup.org/onlinepubs/009695399/functions/select.html)?當然還有'recv'的'MSG_DONTWAIT'標誌(這是Linux專用的擴展)。 – 2013-04-23 07:22:38

回答

7

您可以使用pollselect或類似的東西:

struct pollfd fd; 
int res; 

fd.fd = s; 
fd.events = POLLIN; 
res = poll(&fd, 1, 1000); // 1000 ms timeout 

if (res == 0) 
{ 
    // timeout 
} 
else if (res == -1) 
{ 
    // error 
} 
else 
{ 
    // implies (fd.revents & POLLIN) != 0 
    recv(s,buf,sizeof(buf),0); // we can read ... 
} 
3

我不知道是否有可能設置一個超時的recv

呼叫setsockopt()SO_RCVTIMEO選項。

4

如何爲UDP套接字超時在Linux中:

#include <sys/time.h> 

struct timeval timeout={2,0}; //set timeout for 2 seconds 

/* set receive UDP message timeout */ 

setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(struct timeval)); 

/* Receive UDP message */ 
int recvlen = recvfrom(fd, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr, &slen); 
if (recvlen >= 0) { 
    //Message Received 
} 
else{ 
    //Message Receive Timeout or other error 
} 
+1

-1的返回值可能表示除超時之外的很多事情。檢查'EAGAIN/EWOULDBLOCK'中'errno'的值以確定是否發生超時是非常重要的。 – EJP 2015-02-12 23:14:50