udp的简单整理

2023-09-17 22:52:56

最近思考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

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

#抓包可以看到  收到五个包   前四个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分片试试

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

//这里我在客户端进行设置  然后发送前面的包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

更多推荐

虹科产品 | HK-ATTO 光纤通道卡利用FC-NVMe 提升全闪存存储阵列性能

一、虹科ATTO光纤通道HBA随着对高速数据访问和低延迟存储解决方案的需求日益增长,虹科ATTO最新的光纤通道创新技术带来了改变游戏规则的突破。原生光纤通道和第二代FC-NVMe标准使虹科ATTO光纤通道HBA能够提供无与伦比的速度和效率,显著加快全球数据中心的全闪存阵列性能。原生光纤通道支持可确保数据密集型共享工作负

redis常见问题

Redis的数据结构有哪些?请简要描述它们的特点和应用场景。答:Redis支持的数据结构包括字符串(String)、哈希表(Hash)、列表(List)、集合(Set)、有序集合(SortedSet)等。字符串是最基本的数据类型,可以存储文本或二进制数据。哈希表适合存储对象形式的数据,方便单独读写字段。列表可以用于实现

Redis 五大类型源码及底层实现

面试题:谈谈Redis数据类型的底层数据结构:SDS动态字符串双向链表玉缩列表ziplist哈希表hashtable跳表kiplist整数集合intset快速列表quicklist紧凑列表listpackRedis源代码的核心部分官网:GitHub-redis/redis:Redisisanin-memorydatab

【Redis】关于过期数据清除的一些策略

这里要讨论的为过期的数据是如何被清除的,也就是网上常常讨论的过期清除策略。需要注意的是,redis除了会对过期的数据进行淘汰,也可以通过对内存大小进行限制,并对超出内存限制后进行数据淘汰。此时淘汰的数据未必是过期的,只是因为内存达到限制而被淘汰。需要注意一下两者的区别,数据淘汰算法包括LRU、LFU等。好,回归过期数据

基于Python的海量豆瓣电影、数据获取、数据预处理、数据分析、可视化、大屏设计项目(含数据库)

目录项目介绍研究背景国内外研究现状分析研究目的研究意义研究总体设计网络爬虫介绍豆瓣电影数据的采集数据预处理大数据分析及可视化豆瓣影评结构化分析大屏可视化文本可视化总结每文一语项目介绍有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主!!!!!!!!!!本文基于Python的网络爬虫手段对豆瓣电影网站进行数据

Javascript数据类型和类型转换的应用场景

🎬岸边的风:个人主页🔥个人专栏:《VUE》《javaScript》⛺️生活的理想,就是为了理想的生活!目录基础数据类型和引用数据类型使用typeof操作符包装类型隐式类型转换1.数字转字符串:2.字符串转数字:3.布尔值转数字:4.字符串转布尔值:5.对象的隐式转换显式类型转换类型转换规则1.类型转换的优先级:在J

Python 之plt.plot()的介绍以及使用

文章目录介绍代码实例介绍plt.plot()是Matplotlib库中用于绘制线图(折线图)的主要函数之一。它的作用是将一组数据点连接起来,以可视化数据的趋势、关系或模式。以下是plt.plot()的详细介绍:plt.plot(x,y,fmt,**kwargs)x:表示X轴上的数据点,通常是一个列表、数组或一维序列,用

使用ZoeDepth生成深度估计图

目前单目深度估计分为两个派系,metricdepthestimation(度量深度估计,也称绝对深度估计)和relativedepthestimation(相对深度估计)。ZoeDepth是第一个结合相对和绝对深度的多模态单目深度估计网络。本博文仅记录使用ZoeDepth生成深度估计图的过程(因为直接按项目说明中进行使

【Azure】浅析 Azure 交互工具:Azure 门户、Azure Cloud Shell、 Azure CLI 和 Azure PowerShell | 文末送书

文章目录前言Azure门户AzureCloudShell,包括AzureCLI和AzurePowerShell什么是AzureCloudShell?什么是AzurePowerShell?什么是AzureCLI?对Azure交互的工具在AZ-900中的考点文末送书书籍介绍关于作者获取方式前言本文将深入浅出地探讨Micro

k8s(Kubernetes)集群部署--使用 kubeadm方式部署

k8s集群部署--使用kubeadm方式部署一、测试所需环境(三台均要执行)二、配置准备(三台均要执行)1.重命名hostname、添加hosts2.关闭防火墙、selinux与swap3.添加网桥过滤及内核转发配置文件4.同步时间5.安装ipset及ipvsadm三、安装docker(三台均要执行)1.配置Docke

微服务 第三章 Spring Cloud 简介

系列文章目录第一章Java线程池技术应用第二章CountDownLatch和Semaphone的应用第三章SpringCloud简介文章目录系列文章目录@[TOC](文章目录)前言:SpringCloud是一款基于SpringBoot实现的微服务框架1、SpringCloud的常用组件如下表所示。2、SpringBoo

热文推荐