Linux中recvfrom超时无效的解决方法 (linux recvfrom超时无效)

在Linux系统中,recvfrom函数是常用的接收数据的函数。它可以在指定的时间内等待数据到达,超时则返回-1并设置errno为EWOULDBLOCK或EAGN错误。但是有时候我们在使用这个函数时却发现,超时设置似乎没有生效,无论等待多长时间,函数都不会返回,这是为什么呢?本文将介绍这个问题的原因和解决方法。

问题原因

recvfrom函数的超时是依赖于套接字选项SO_RCVTIMEO的,该选项设置了套接字的接收超时时间。我们在调用recvfrom函数前需要通过setsockopt函数设置套接字选项,如下所示:

“`C++

#include

int setsockopt(int sockfd, int level, int optname,

const void *optval, socklen_t optlen);

“`

其中,sockfd表示要操作的套接字描述符;level表示选项定义的协议层。对于套接字选项SO_RCVTIMEO,level应该是SOL_SOCKET;optname表示要设置的选项名,对于SO_RCVTIMEO,应该设置为SO_RCVTIMEO;optval和optlen分别是设置选项的值和长度。

例如,我们可以将发送和接收超时时间设置为10秒:

“`C++

struct timeval tv;

tv.tv_sec = 10;

tv.tv_usec = 0;

setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

“`

然而,有一些情况下,我们会发现即使设置了超时时间,recvfrom函数依然会一直阻塞而不返回。这是因为Linux内核对SO_RCVTIMEO有一些限制,如果不满足这些限制,超时设置就会无效。下面我们来分析一下这些限制。

Linux内核的限制

1. 数据包长时间在网络中传输,但是没有到达接收方时,recvfrom会一直等待,超时设置失效。这是因为SO_RCVTIMEO只适用于数据已经到达了接收缓冲区的情况,对于还在网络中传输的数据,内核并不会考虑等待超时的情况。如果要在这种情况下使用超时设置,我们需要使用select函数等待,它能够等待一段时间并检查套接字是否有数据可读。

2. 数据包可能已经到达了接收缓冲区,但是仍然没有被recvfrom函数读取,这时recvfrom函数会一直等待,超时设置失效。如果我们在调用recvfrom函数时指定的缓冲区大小小于数据包大小,或是多次调用recvfrom函数时指定的缓冲区大小总和小于数据包大小,就会出现这种情况。解决方法是尽可能保证缓冲区的大小大于等于更大的数据包大小,或使用MSG_PEEK标志调用recvfrom函数,查看数据包大小后再次调用recvfrom函数读取数据。

3. SO_RCVTIMEO的最小超时时间为20毫秒,如果设置的超时时间小于20毫秒,超时设置会被忽略。这是因为Linux内核采用了一种轮询方式实现SO_RCVTIMEO,如果超时时间小于20毫秒,轮询的开销将过大,因此会忽略超时设置。如果要设置更小的超时时间,可以使用其他的方法,如使用select函数以及epoll函数。

解决方法

有了以上的分析,我们可以得出以下的解决方法:

1. 当数据包长时间在网络中传输时,使用select函数等待可读,而不是设置超时时间等待。

2. 确保指定的缓冲区大小大于等于更大的数据包大小,或使用MSG_PEEK标志调用recvfrom函数。

3. 设置的超时时间应该大于等于20毫秒,否则会被忽略。

4. 如果需要更细粒度的超时时间控制,可以使用其他的方法,如使用select函数以及epoll函数。

相关问题拓展阅读:

  • Linux udp通信不成功
  • linuxsend返回值为9
  • 使用recvfrom接收UDP包在Windows和Linux平台的不同表现

Linux udp通信不成功

server端绑定消渗余地拿滚址错误。通常喊枣是

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

可能是内存的问题,也可能是程序的兼容性问题.

linuxsend返回值为9

linuxsend返回值为9:

linuxsend返回值为9因为OS Linux Mint 14.客户端在启动时向服务器发送请求以获取一些会话参数,包括usec中的超时 . 客户端打开一个套接字并设置一个默认轿陪蠢超时值,以便在recvfrom上不被无限制地阻塞,然后发送对这些参数的请求,乱御关闭所述套接字,重新打开设置新超时值的套接字,最后询问用户用于命令 .

参数请求由子函数处理,该子函数除了其他之外还获得指向闭陪客户端套接字的指针,因此如果新的sockfd是不同的数字,则主函数也将能够引用新的套接字 . (返回值用作检查值,零或非零)

linuxsend返回值为9,这蠢或个的话根据厂商发布的数据以及我迟档山的朋友的反馈来看的话,这个是完码中全正常的。

使用recvfrom接收UDP包在Windows和Linux平台的不同表现

1 UDP接收原理

操作系统的UDP接收流程如下:收到一个UDP包后,验证没有错误后,放入一个包队列中,队列中的每一个元素就是一个完整的UDP包。当应用程序通过recvfrom()读取时,OS把相应的一个完整UDP包取出,然后拷贝到用户提供的内存中,物理用户提供的内存大小是多少,OS都会完整取出一个UDP包。如果用户提供的内存小于这个UDP包的大小,那么在填充慢内存后,UDP包剩余的部分就会被丢弃,以后再也无法取回。

这与TCP接收完全不同,TCP没有完整包的概念,也没有边界,OS只旁改会取出用户要求的大小,剩余的仍然保留在OS中,下次还可以继续取出。

socket编程虽然是事实上的标氏氏准,而且不同平台提供的接口函数也非常类似,歼启散但毕竟它不存在严格的标准。所以各个平台的实现也不完全兼容。下面就从recvfrom()这个函数看看Window平台和Linux平台的不同。

2 Windows平台的表现

先看头文件中的声明:

view plaincopy在CODE上查看代码片派生到我的代码片

int

WSAAPI

recvfrom(

_In_ SOCKET s,

_Out_writes_bytes_to_(len, return) __out_data_source(NETWORK) char FAR * buf,

_In_ int len,

_In_ int flags,

_Out_writes_bytes_to_opt_(*fromlen, *fromlen) struct sockaddr FAR * from,

_Inout_opt_ int FAR * fromlen

);

再看MSDN说明:

If the datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and recvfrom generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost.

可以看出,buf大小小于UDP包大小的时候,recvfrom()会返回-1,并设置错误WSAEMSGSIZE。

实际编程测试验证确实是这样的表现。

3 Linux平台的表现

先看头文件中的声明:

view plaincopy在CODE上查看代码片派生到我的代码片

__extern_always_inline ssize_t

recvfrom (int __fd, void *__restrict __buf, size_t __n, int __flags,

__SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len)

可以看出与Windows平台的函数原型相同。但是在其man手册里,没有看到UDP包大于接收缓冲区情况的特殊说明。

写代码测试表明,buf小于UDP包大小的时候,recvfrom()仍然返回复制到缓冲区的字节数,调用者无法得知UDP包被截断的情况。

4 写代码注意事项

UDP包更大是多大呢?UDP头部大小字段占16字节,所以理论上是65535个字节大小。但是UDP如果是通过IP(大多数情况)来传送,由于UDP本身不支持分片,所以一个UDP包只能通过一个IP包来传送,一个IP包大大小理论上也是用16字节表示,这样UDP更大大小就是(65535-IP头部)。

而现实中如果IP包大小大于底层链路层帧的更大数据区大小,则必须对IP包进行分片传送。分片会严重影响传送效率,而且增大不稳定性,所以实际的网络程序发送的IP包都封装到单一的链路层帧中,从而避免分片。问题是链路层帧是多大呢?答案是不一定,因为不同的物理网络的帧大小不一样,如以太网是1500字节,但是其他物理网络可能更小,Internet上的有个最小的限制,那就是576字节。如果UDP程序运行在只运行在以太网中,那么为了避免IP分片,可以采用的更大大小为()=1472字节。如果UDP程序需要运行在Internet上,那么建议更大大小为()=548字节。

linux recvfrom超时无效的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux recvfrom超时无效,Linux中recvfrom超时无效的解决方法,Linux udp通信不成功,linuxsend返回值为9,使用recvfrom接收UDP包在Windows和Linux平台的不同表现的信息别忘了在本站进行查找喔。

香港服务器首选树叶云,2H2G首月10元开通。
树叶云(shuyeidc.com)提供简单好用,价格厚道的香港/美国云服务器和独立服务器。IDC+ISP+ICP资质。ARIN和APNIC会员。成熟技术团队15年行业经验。

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/185060.html<

(0)
运维的头像运维
上一篇2025-03-29 04:21
下一篇 2025-03-29 04:23

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注