UDP 套接字设置超时

Posted

技术标签:

【中文标题】UDP 套接字设置超时【英文标题】:UDP Socket Set Timeout 【发布时间】:2012-11-12 22:03:05 【问题描述】:

我正在尝试在 UDP 套接字上设置 100 毫秒的超时。我正在使用 C。我在下面发布了我的相关代码。我不确定为什么这没有超时,而是在没有收到段时挂起。这是否仅适用于未使用 bind() 方法绑定的套接字?

#define TIMEOUT_MS      100     /* Seconds between retransmits */

if ((rcv_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    DieWithError("socket() failed");

if ((rcv_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    DieWithError("socket() failed");

//set timer for recv_socket
static int timeout = TIMEOUT_MS;
setsockopt(rcv_sock, SOL_SOCKET, SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));

if(recvfrom(rcv_sock, ackBuffer,sizeof(ackBuffer), 0,
       (struct sockaddr *) &servAddr2, &fromSize) < 0)
    //timeout reached
    printf("Timout reached. Resending segment %d\n", seq_num);
    num_timeouts++;

【问题讨论】:

您似乎没有检查来自setsockopt 的返回值以查看它是否返回错误。它可能是。 SO_RCVTIMEO 在 Linux 和 MacOS 上均记录为采用 struct timeval,但您传递的是 int。尝试通过 struct timeval 代替。另外,为什么要将&amp;timeout 转换为char *?这根本不是char * 【参考方案1】:

我也有同样的问题。我尝试采用您建议的解决方案,使用 timeval 结构。但它似乎没有用。

我已经阅读了微软的文档,时间应该是DWORD和毫秒数,但还有另一件事要做,如果套接字是使用WSASocket函数创建的,那么@987654324 @ 参数必须设置WSA_FLAG_OVERLAPPED 属性才能使超时正常工作。 否则超时永远不会生效。

【讨论】:

接受的答案以 POSIX 套接字为目标。 Windows 提供了自己的套接字 API,因此接受的答案不适用于 Windows。【参考方案2】:

SO_RCVTIMEO 选项需要在sys/time.h 中定义的struct timeval,而不是像您传递给它的整数。 timeval struct 具有秒字段和微秒字段。要将超时设置为 100 毫秒,以下应该可以解决问题:

struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 100000;
if (setsockopt(rcv_sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) < 0) 
    perror("Error");

【讨论】:

以上是关于UDP 套接字设置超时的主要内容,如果未能解决你的问题,请参考以下文章

java-接收UDP包时设置超时函数java

为 UDP 模拟 accept()(设置解复用 UDP 套接字的时间问题)

基于UDP协议的网络程序

资源暂时不可用,UDP socket

设置 UDP 套接字的源 IP

使用 boost asio udp 套接字时如何设置本地端点