udp的简单整理

最近思考udp处理的一些细节,根据公开课,反复思考,终于有所理解,做整理备用。

0:简单汇总

1:udp是基于报文传输的,接收方收取数据时要一次性读完。
2:借助udp进行发包,发大包也是没有问题的,借助IP层ip分片。

===》ip分片可以发生在原始主机上,也可以发生在中间路由器上(MTU值)

===》ip分片后,可以再分片,中间根据MTU进行判断。

===》网络状态良好情况下问题不大,但是网络状况不好的话,如果分片后丢弃其中一个包,udp整个包就丢了。

3:有的路由器可以设置,udp包过大会丢弃(设置了不允许分包吗?)。

===》ip头部有个标志字段flag,可以设置不能分片,则路由器会丢包。

4:路由器会有小包优先发送的问题,因此,发送大包会有乱序问题(分片后先发后面包的策略吧?)。

===》这个是分片后先发的后面包吧。

5:用户层对udp做分包

===》网络状况不好时,依赖ip分包,丢一个包整个包会丢,增加了风险和延迟。

===》设置了udp底层不允许分包,必然丢包。

===》网络发生拥塞,路由器或者交换机可能丢弃较大包减轻压力。

需要关注:

===》在用户层对udp进行分包, 需要自定义协议以便组包,以及分析包的最大字节数。

===》组包乱序问题,走不同链路可能导致,路由器先发送小包可能导致。

6:udp数据报大小,最大65535字节(报文头2字节表示长度),64k = 64*1024=65535字节

1:udp发包,如果一次不读完,就读不到完整数据了。

//借助demo进行测试,分包后,发送如下,前四个包1400字节 最后一个891

//这里直接借助同一个虚拟机,客户端和服务端都运行在其上测试。

bash 复制代码
#抓包可以看到  收到五个包   前四个1428字节 最后 总共919字节
root@ubuntu:/home/ubuntu# tcpdump -i lo -vnn port 10000
tcpdump: listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:33:04.369612 IP (tos 0x0, ttl 64, id 35196, offset 0, flags [DF], proto UDP (17), length 1428)
    192.168.40.132.48617 > 192.168.40.132.10000: UDP, length 1400
10:33:04.369764 IP (tos 0x0, ttl 64, id 35197, offset 0, flags [DF], proto UDP (17), length 1428)
    192.168.40.132.48617 > 192.168.40.132.10000: UDP, length 1400
10:33:04.369830 IP (tos 0x0, ttl 64, id 35198, offset 0, flags [DF], proto UDP (17), length 1428)
    192.168.40.132.48617 > 192.168.40.132.10000: UDP, length 1400
10:33:04.369889 IP (tos 0x0, ttl 64, id 35199, offset 0, flags [DF], proto UDP (17), length 1428)
    192.168.40.132.48617 > 192.168.40.132.10000: UDP, length 1400
10:33:04.369993 IP (tos 0x0, ttl 64, id 35200, offset 0, flags [DF], proto UDP (17), length 919)
    192.168.40.132.48617 > 192.168.40.132.10000: UDP, length 891

#分析代码,如果服务端读数据的时候buffer缓冲区不够大,只读特定长度的数据,一个完整的包就只读了这部分,后面的数据就全不在了 
#这里分析了 最后客户端发送时的buffer内容 以及服务端接收buffer的内容,
#虽然有while循环,但是只读了一次,如果buffer不够,只读了一个发送报文的前部分,后面在读就从新的报文的前面了。

#===》所以 代码一次性要读完发送出来的一个完整的包

2:udp发包,发大包也没问题,ip底层会分片(发送端或者中间路由)。

==》可能多次分片

这里简单实现一个udp服务端的代码,在本地局域网和远端服务器上进行部署看看现象。

2.1 借助网络传输助手,在虚拟机上运行服务端,客户端用网络传输助手发送大包,抓包发现是一个包,并且,服务端正常打印了数据。

接收时recvfrom缓冲区设置的比较大,是20000

2.2 在远端云服务器上进行测试:同样的服务端代码运行在远端

这里遇到一个自己埋坑的点,看了好久,云服务器上要配置端口开放,配置安全组,配置完要加入到对应的云服务器环境中,我配置后,实际环境和配置的安全组不是一个,一直不通研究了半天。

如果用网络传输助手直接发一个比较大的包,发现也是能成功的。(这里的udpserver仅仅大的buffer接收)

我简单测试,发送了8次,发现8次都收到了,这里是手动,频率不高

用代码测试,在本机虚拟机上发多个包给云服务器上demo

可以看到,前三次发2048个字节,最后一个335字节,可以看到有接收乱序的问题。

如果我给客户端的发送,多发送几次(这里3次),并且不等待,能明显看出乱序严重,有收到包。

===》这里说明超过MTU,借助ip分片,接收还是可以的,但是有乱序的问题

如果正常的包大小进行测试看看,小于MTU,这里用1400:

3:udp发包,假设路由器有设置不允许分片,或者设置不允许ip分片试试

如果我设置不允许分包,这里只是简单参考设置:

c++ 复制代码
//这里我在客户端进行设置  然后发送前面的包1800  最后一个包符合
int val = IP_PMTUDISC_DO ;
setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val));

从抓包看,如果有这样的设置,那么大于MTU的包就直接丢弃了,sendto报时失败了,没有ip分片,不知道路由器中间有没有限制。

设置后,直接导致发送失败:

这里有个路径MTU的概念,以及设置ip不分片,有待研究

汇总:

1:udp如果直接发大于MTU的包,一般网络状况好的情况下也不会有太大问题,当然有丢包概率。

2:udp发送时,有乱序的问题。

3:在网络状态不好的情况下,借助了ip分片,增大了丢包的概率。

4:路径MTU,以及中间路由器对包的丢包策略也是一个点,

5:为了防止丢包,乱序,以及中间路由器相关不可控问题,最好用户层进行拆包,拼包处理,以及相关的可靠性传输。

太多的技术栈来源于零声学院,工作之余,跟着研究一些工作之外的知识。

推荐:https://xxetb.xet.tech/s/2W52YR

相关推荐
sunfove7 小时前
光网络的立交桥:光开关 (Optical Switch) 原理与主流技术解析
网络
Kevin Wang7279 小时前
欧拉系统服务部署注意事项
网络·windows
min1811234569 小时前
深度伪造内容的检测与溯源技术
大数据·网络·人工智能
汤愈韬10 小时前
NAT策略
网络协议·网络安全·security·huawei
汤愈韬10 小时前
Full Cone Nat
网络·网络协议·网络安全·security·huawei
zbtlink10 小时前
现在还需要带电池的路由器吗?是用来干嘛的?
网络·智能路由器
桌面运维家10 小时前
vDisk配置漂移怎么办?VOI/IDV架构故障快速修复
网络·架构
dalerkd10 小时前
忙里偷闲叙-谈谈最近两年
网络·安全·web安全
汤愈韬11 小时前
NAT ALG (应用层网关)
网络·网络协议·网络安全·security·huawei
运维栈记12 小时前
虚拟化网络的根基-网络命名空间
网络·docker·容器