udp丢包 又是udp丢包

本文探讨了UDP传输中丢包的常见原因,并提供了多种解决方案。包括优化接收缓冲、处理大包、减小发送频率等方法。同时,文章还介绍了在不同场景下可能遇到的特定问题及其解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自己在做UDP传输时遇到的问题,接收端没设置缓存,结果总是丢包。

看到这篇文章设置了一下接收缓存就好

int nRecvBuf=32*1024;//设置为32K
setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));



http://www.cnweblog.com/fly2700/archive/2011/09/19/317825.html


什么会导致udp丢包呢,我这里列举了如下几点原因:

1.调用recv方法接收端收到数据后,处理数据花了一些时间,处理完后再次调用recv方法,在这二次调用间隔里,发过来的包可能丢失。对于这种情况可以修改接收端,将包接收后存入一个缓冲区,然后迅速返回继续recv。
2.发送的包巨大丢包。虽然send方法会帮你做大包切割成小包发送的事情,但包太大也不行。例如超过30K的一个udp包,不切割直接通过send方法发送也会导致这个包丢失。这种情况需要切割成小包再逐个send。
3.发送的包较大,超过mtu size数倍,几个大的udp包可能会超过接收者的缓冲,导致丢包。这种情况可以设置socket接收缓冲。以前遇到过这种问题,我把接收缓冲设置成64K就解决了。
int nRecvBuf=32*1024;//设置为32K
setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
4.发送的包频率太快,虽然每个包的大小都小于mtu size 但是频率太快,例如40多个mut size的包连续发送中间不sleep,也有可能导致丢包。这种情况也有时可以通过设置socket接收缓冲解决,但有时解决不了。
5.发送的广播包或组播包在windws和linux下都接收正常,而arm上接收出现丢包。这个还不好解决,我的解决方法是大包切割成大小为1448的小包发送,每个包之间sleep 1毫秒,虽然笨,但有效。我这里mtu size为1500字节,减去udp包头8个字节,减去传输层几十个字节,实际数据位1448字节。
除此之外还可以试试设置arm操作系统缓冲:
//设置mtu size 1500最大
ifconfig eth0 mtu 1500
//查看接收缓冲最大和默认大小。
sysctl -A | grep rmem
//设置接收缓冲的最大大小
sysctl -w net.core.rmem_max=1048576
sysctl -w net.core.rmem_default=1048576
sysctl -w net.ipv4.udp_mem=1048576
sysctl -w net.ipv4.udp_rmem_min=1048576
6,局域网内不丢包,公网上丢包。这个问题我也是通过切割小包并sleep发送解决的。如果流量太大,这个办法也不灵了。


总之udp丢包总是会有的,如果出现了用我的方法解决不了,还有这个几个方法: 要么减小流量,要么换tcp协议传输,要么做丢包重传的工作。

### 如何通过UDP/TCP实现快速且可靠的数据传输 #### TCP 的可靠性机制 TCP 是一种面向连接的、可靠的传输协议,其核心在于确保数据的完整性和顺序性。以下是 TCP 实现可靠数据传输的关键技术: - **序列号和确认号** 每个 TCP 报文段都有一个唯一的序列号,接收方会返回 ACK 确认消息来告知发送方已成功接收到哪些数据[^1]。 - **超时重传** 如果发送方未在规定时间内收到 ACK,则认为该数据可能丢失并重新发送相应的报文段。 - **冗余确认 (Duplicate Acknowledgment)** 当接收方连续多次接收到重复数据时,它会向发送方发出多个相同的 ACK 来提示可能存在数据丢失的情况,从而触发快速重传机制。 - **流量控制** 使用滑动窗口机制调节双方之间的数据流速率,防止过载导致丢包现象发生。 - **拥塞控制** 包括四种主要算法:“慢启动”、“拥塞避免”、“快重传”以及“快恢复”,这些策略共同作用以优化网络性能并减少延迟时间。 #### UDP 改进方案用于提高可靠性 尽管 UDP 缺乏内置错误检测功能,但它可以通过额外的应用层设计达到接近于 TCP 的效果: - **自定义握手过程** 建立类似于三次握手机制的过程来进行初始化连接验证, 这样可以在一定程度上模仿 tcp 风格的安全链接建立方式. - **加入校验字段** 在原有 udp 头部之外再附加一层crc或者md5之类的hash值用来检验整个packet的内容一致性.[^3] - **实施acknowledge反馈环路** 类似tcp那样设置应答帧结构通知源端那些packets已经被正确获取到; 同时也可以考虑引入nack否定回应以便更迅速定位问题所在位置. - **运用fragmentation分片重组逻辑** 将大数据块拆分成若干个小片段单独处理后再拼合还原成原始形态传递给目标设备完成最终交付动作.[^2] #### 综合最佳实践建议 对于追求极致效能又不想牺牲太多稳定度的任务场景来说, 结合两者各自优点形成混合型架构不失为明智之举. 即利用udp打底承载基础通讯框架之上叠加必要的纠错补偿措施构建起兼顾速度与质量的新一代解决方案体系. ```python import socket def send_with_ack(data, addr): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) while True: sent = sock.sendto(data, addr) # Wait for acknowledgment from receiver. try: ack_data, server_addr = sock.recvfrom(1024) if ack_data.decode('utf-8') == 'ACK': break except TimeoutError: continue sock.close() ``` 上述代码展示了一个简单的基于 UDP 并带有基本确认机制的例子。其中 `send_with_ack` 函数尝试不断发送直到获得来自对方的有效响应为止才停止循环退出程序运行流程。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值