2013-04-23 108 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