设置UDP套接字的recv函数超时时间

4
我使用 sendto 发送 UDP 数据包,然后通过 recv 接收答案。如果 recv 没有接收到回复,程序将无法继续进行。但是,UDP 数据包可能会丢失,或者由于某些原因,数据包可能无法被传递,以至于程序会卡在 recv 行上。我想知道如何设置 recv 的超时时间,如果在一分钟内没有收到任何数据包,则跳过该行并继续执行代码?
我没有粘贴完整的代码,因为它是通用的 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 进行轮询?当然,还有 recvMSG_DONTWAIT 标志(这是 Linux 特定的扩展)。 - Some programmer dude
3个回答

12
在Linux中如何为UDP套接字设置超时时间:
#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
}

4
返回值为-1可能表示除超时外的许多其他情况。必须检查errno的值以确定是否发生了超时,可能是EAGAIN/EWOULDBLOCK。请注意,不要更改原始含义并确保内容通俗易懂。 - user207421

8
你可以使用“poll”、“select”或类似的工具:
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 设置超时时间。

使用 SO_RCVTIMEO 选项调用 setsockopt()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接