当前位置: 首页 > news >正文

udp发送数据如果超过1个mtu时,抓包所遇到的问题记录说明

最近在测试Syslog udp发送相关功能,测试环境是centos
udp头部的数据长度是2个字节,最大传输长度理论上是65535,除去头部这些字节,可以大概的说是64k。

写了一个超过64k的数据(随便用了一个7w字节的buffer)发送demo,打印的是:Error: Message too long,sendto返回值是-1。接收端也没有收到

int UDPClient::Send(const char *buffer, int length)66 {67         if (mb_closed) {68                 //HLog(HGET_ERROR<<L"soket was closed.");6970                 return -1;71         }72         int i = sendto(mi_sock_fd, buffer, length, 0,73                 (sockaddr *)&serverAddr, sizeof(serverAddr));7475         fprintf(stderr, "Error: %s\n", strerror(errno));76         return i;77 }

而后又用了一个5w字节的buffer发送,这次发送是正常的
请添加图片描述
接收端开启的是linux自带的rsyslog服务,接收到的日志写入了/var/log/messages,查看文件接收到的数据长度也符合。

请添加图片描述
不过发送端和接收端双端抓包都只抓到一条,且长度不符合发送的长度5w,总共时一个mtu,大概可以知道只是抓到了一个分片,但是后序的包为什么抓不到呢
tcpdump -i ens192 -vvvv -s0 udp port 514
请添加图片描述
而后我们再StackOverflow上发现了:

That’s probably because whatever traffic is going to port 5201 consists of UDP packets that are larger than what would fit in a single link-layer packet, so IP has to fragment them.

That filter, unfortunately, will only capture the first fragment, because the OS filtering mechanism that libpcap uses does filtering on a packet-by-packet basis without maintaining any packet history, and either 1) the first fragment of a fragmented UDP packet will contain the full UDP header, and the others will not have any information to identify them as being additional fragments of that fragmented packet (without packet history, the IP identifier doesn’t help) or 2) the UDP header itself is fragmented, in which case the filter won’t work at all (that will probably never happen in practice, but it’s not ruled out by RFC 791). Additional fragments won’t be captured, so you won’t have the full packet.

意思是:当发送到端口的流量包含大于单个链路层数据包能够承载的UDP数据包时,IP层会将这些数据包进行分片处理。第一个UDP数据包的分片会包含完整的UDP头部,但后续的分片则不包含UDP头部。由于过滤机制是基于单个数据包进行的,且没有维护数据包历史,因此后续的分片在没有额外信息的情况下无法被识别为属于同一个原始UDP数据包的碎片。IP标识符虽然可以用于区分不同的分片是否属于同一个原始IP数据包,但它并不足以在没有额外上下文的情况下确定这些分片是否属于同一个UDP会话。

所以调整下抓包命令,去掉端口参数,发现可以抓到完整的包。
tcpdump -i ens192 -vvvv -s0 udp -w /tmp/20240703.pcap
请添加图片描述
所以:udp发送超过64k(大概的数字,除去ip和udp头部长度),需要开发人员在应用层把消息分片,不然系统的发送接口sendto会报错(message too long),返回-1,发送失败,接收端收不到任何消息。

如果消息长度是64k以内,不需要开发人员在应用层分片,发送不会失败,但是单次最大长度是1500-头部,大概1400多,也就是会分片传多次,接收端会自行会重组数据的,但不会校验,如果在传输过程中有数据包丢失或损坏,接收端可能无法重组出完整的数据。接收端无法重组出完整的数据,那么这个包整个会被放弃,所以udp传输要么全部收到,要么全部收不到,没有收到一半的情况

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 9 redis,memcached,nginx网络组件
  • 单/多线程--协程--异步爬虫
  • 洛谷 P2141 [NOIP2014 普及组] 珠心算测验
  • Harris点云关键点检测
  • 三、docker配置阿里云镜像仓库并配置docker代理
  • 使用瀚高数据库开发管理工具进行数据的备份与恢复---国产瀚高数据库工作笔记008
  • 使用Python绘制堆积柱形图
  • Ubuntu22.04使用/etc/rc.local开机启动程序
  • Stable Diffusion:最全详细图解
  • Leetcode1115 交替打印 FooBar及其测试
  • 这款新的 AI 语音助手击败了 OpenAI,成为 ChatGPT 最受期待的功能之一
  • Java 7新特性深度解析:提升效率与功能
  • Java中的数据可视化与图表库选择
  • 【TORCH】绘制权重分布直方图,权重torch.fmod对torch.normal生成的随机数进行取模运算
  • Codeforces Round 954 (Div. 3)
  • 【面试系列】之二:关于js原型
  • 07.Android之多媒体问题
  • C# 免费离线人脸识别 2.0 Demo
  • ES6 学习笔记(一)let,const和解构赋值
  • java正则表式的使用
  • Sass 快速入门教程
  • storm drpc实例
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • Vue学习第二天
  • 代理模式
  • 和 || 运算
  • 机器学习学习笔记一
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 爬虫模拟登陆 SegmentFault
  • 前端设计模式
  • 我与Jetbrains的这些年
  • 移动端解决方案学习记录
  • ​如何使用QGIS制作三维建筑
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • # Spring Cloud Alibaba Nacos_配置中心与服务发现(四)
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (1)(1.13) SiK无线电高级配置(五)
  • (1)STL算法之遍历容器
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (函数)颠倒字符串顺序(C语言)
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (七)Flink Watermark
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (转)IOS中获取各种文件的目录路径的方法
  • (转)Java socket中关闭IO流后,发生什么事?(以关闭输出流为例) .
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .jks文件(JAVA KeyStore)
  • .net core webapi 大文件上传到wwwroot文件夹
  • .NET业务框架的构建
  • .vimrc 配置项
  • :O)修改linux硬件时间