UDP协议报文分析和主动发送UDP简单实现

news/2024/5/18 15:59:48 标签: udp, wireshark

UDP协议报文分析和主动发送UDP简单实现

  • 前言
  • 一、Wireshark 报文解析
    • 1、UDP报文实例
    • 2、报文格式分析
      • ①、以太网头
      • ②、IP头
      • ③、UDP头
  • 二、UDP主动传输数据的实现方式
    • 1、说明
    • 2、发送UDP前的约定
    • 3、ARP报文
    • 4、UDPIP报文
  • 三、UDP报文校验
    • 1、IP校验和计算
    • 2、UDP校验和计算

前言

  用 Wireshark 简单分析UDP报文解析,学习UDP报文的解析。在需要编写底层UDP报文的环境下(单片机等),简单编排UDP报文达到主动传输的目的。

一、Wireshark 报文解析

1、UDP报文实例

  
在这里插入图片描述

2、报文格式分析

  一帧UDP报文由四个部分组成:以太网头、IP头、UDP头、数据。

帧头帧数据含义对应报文(HEX)位数
以太网头目标MAC地址00:aa:00:00:00:7b6*8
源MAC地址e0:db:55:f8:d1:e56*8
协议类型08 002*8
IP头IP协议版本44
IP头长度54
服务类型TOS008
报文总长度(IP报文开始)00 212*8
标识符(序号)c2 a12*8
标志位 00 002*8
帧存活周期TTL408
数据协议118
IP校验和32 502*8
源IP地址c0 a8 02 0f4*8
目标IP地址c0 a8 02 7b4*8
UDP头源端口号2c ee2*8
目标端口号01 f62*8
报文总长度(UDP报文开始)00 0d2*8
UDP校验和17 f32*8
数据帧传输数据11 11 11 11 11n*8

①、以太网头

以太网头常用格式
  以太网头使用两种标准帧格式。第一种是上世纪80年代初提出的DIXv2格式,即EthernetII帧格式。EthernetII后来被IEEE802标准接纳,并写进了IEEE802.3x-1997的3.2.6节。第二种是1983年提出的IEEE802.3格式。普通情况下使用EthernetII帧格式更简单便捷。
  报文中 Type 为" 08 00 "表示后续报文的协议为IP协议帧,若 Type 为"08 06 "表示后续报文为ARP帧。
  

②、IP头

  若为主动发送的UDP报文,IP头中开头的“45 00”以及“00 00 40 11”可以不用修改,主要修改其他数据。其中“40”表示帧存活时间为64秒,“11”表示后续协议为UDP协议。
  IP头的数据帧主要修改的部分为:IP头开始的数据长度、标识符id、IP校验、对端IP、本机IP。
  数据长度:IP头的长度+后续报文长度。例如实例中的报文长度为0x0021(33),即IP头长度20、UDP头长度8和数据长度5相加(20+8+5)而来。
  标识符ID:可以理解为报文的编号,一般是由上一帧的标识符计算加一。
  对端IP:目标IP地址。
  本机IP:本机IP地址。
  

③、UDP头

  UDP头的数据帧主要注意UDP校验和的计算方式,需要同时计算UDP伪首部。

二、UDP主动传输数据的实现方式

1、说明

  以下方法的测试环境是在局域网内,且无其他设备同时连接的环境下实现的,仅用与点对点的传输方式。

2、发送UDP前的约定

  在发送UDP报文前,想要对端设备收到UDP报文,就必须知道对端的设备部分信息:目标MAC地址、目标IP地址、目标端口号。其中目标IP地址和目标端口号可以在约定后直接进行绑定,但目标MAC地址在很多情况下无法直接得出,且在对端设备更换后会随着变动。此时,我们可以用ARP协议获取MAC地址。

3、ARP报文

  ARP(Address Resolution Protocol),地址解析协议,是根据IP地址获取物理地址的一个TCP/IP协议。
  在发送UDP报文前,可以先发送一帧ARP报文请求,报文需要修改的部分为:本机MAC地址(30:3a:64:9f:32:06)、本机IP(0xc0a8 0067)、目标IP(0xc0a8 0065),其他部分可以参照图中请求报文的数据直接写死。报文中 06 04 后的两个字节是Opcode, 00 01 表示ARP请求报文,若为 00 02 表示应答报文。
  发送ARP报文后会收到ARP的回复报文,回复报文中包含目标IP地址和MAC地址,和本机的IP地址和MAC地址,可以在确认ARP回复报文的目标IP为本机IP后,再将该MAC地址缓存,取得需要的MAC地址为(3e:c8:be:6e:f4:06)。
  ARP报文举例,如图所示:
  请求报文:
请求报文
  应答报文:
应答报文

4、UDPIP报文

  通过ARP报文获取到对端MAC地址后,就可以开始编辑发送UDP报文了。
  (1)编写以太网头部。 写入目标MAC地址(00:aa:00:00:00:7b)、本机MAC地址(e0:db:55:f8:d1:e5)、Type(0x08 00)。
  (2)将IP头的数据长度、IP校验和的四个字节置为0,先填充的IP头部的其他位。 写入IP版本以及长度(0x45)、区分服务领域(0x00)、ID号(0xc2 a1)、标志位Flags(0x00)、ttl(0x40)、协议号(0x11)、本机IP地址(0xc0 a8 02 0f)、目标IP地址(0xc0 a8 02 7b)。
  (3)将UDP头的数据长度、IP校验和的四个字节置为0,先填充的UDP头部的其他位。 写入本机源端口(0x2c ee)、目标端口(0x01 f6)、ID号(0x00 00)。
  (4)填充UDP需要传输的数据。 在UDP报文头之后写入需要传输的数据(0x11 11 11 11 11)。
  (5)根据传输的数据长度,填充IP头中的总长度(0x00 21)。 该长度计算方式为:IP头报文长度20 + UDP报文头长度8 + 数据长度5 = 33。
  (6)根据传输的数据长度,填充UDP头中的总长度(0x00 0d)。 该长度计算方式为:UDP报文头长度8 + 数据长度5 = 13。
  (7)根据IP头报文已填充数据,计算校验和,填充IP头中的校验位(0x32 50)。
  (7)根据IP头和UDP头报文已填充数据,计算校验和,填充UDP头中的校验位(0x17 f3)。

三、UDP报文校验

1、IP校验和计算

  对IP报文头从首部开始以16bit为单位求和,将计算结果溢出16bit的部分加在低16bit上,取反。
  忽略校验位数据,将上述实例报文的IP头从首部开始以16bit为单位拆分后,得到一组数据:0x4500,0x0021,0xC2A1,0x0000,0x4011,0xC0A8,0x020F,0xC0A8,0x027B。
  将上述拆分的16bit数据累加:   0x4500+0x0021+0xC2A1+0x0000+0x4011+0xC0A8+0x020F+0xC0A8+0x027B=0x2 CDAD;
  将上结果的高16位加在低16位数据得到:0xCDAF;
  将得到的0xCDAF作位取反得:0x3250。
简单代码段如下:

/*sendbuf[]是要发送的报文,计算前要先填充其他数据*/
static u16_t
ipchksum()
{
  u16_t i,index=14; //从sendbuf[14]开始计算,即IP头开始位置。
  u32_t sum=0;

  for(i=0;i<5;i++){
	  sum+=((u16_t)sendbuf[index]<<8)+sendbuf[index+1];
	  index+=2;
  }
  index+=2;
  for(i=0;i<4;i++){
	  sum+=((u16_t)sendbuf[index]<<8)+sendbuf[index+1];
	  index+=2;
  }

  sum = (sum >> 16) + (sum & 0xffff);

  return (~sum & 0xffff);
}

2、UDP校验和计算

  对UDP报文头从首部开始以16bit为单位求和,求和时包含后续所有数据以及UDP伪首部数据;将计算结果溢出16bit的部分加在低16bit上,取反。
  (1)先计算伪首部,伪首部由四部分组成:源地址(0xc0a8,0x020f)、目的地址(0xc0a8,0x027b)、UDP数据长度(0x000d)、协议类型(0x0011)。将UDP伪首部以16位求和得到(0x0001 85F8)。
  (2)再计算UDP头部报文,由四部分组成:源端口(0x2cee)、目标端口(0x01f6)、UDP数据长度(0x000d)、数据(0x1111、0x1111、0x1100)。以16位求和得到(0x6213)。这里要注意的是数据结尾如果为单数,需要在低8位填充0x00,而不是高八位填充,即0x11填充为0x1100再求和。
  (3)将UDP的伪首部和与UDP头部和求和(0x1 85f8 + 0x6213);将计算结果的高16位加到低16位得到(0xe80c);进行取反运算,得到最终UDP校验和0x17f3。

简单代码段如下。

/*sendbuf[]是要发送的报文,计算前要先填充其他数据*/
static u16_t
udpchksum(u16_t datalen)
{
  u16_t i,index=26;
  u32_t sum=0;

  sum = 0x11; //计算伪首部
  for(i=0;i<7;i++){
	  sum+=((u16_t)sendbuf[index]<<8)+sendbuf[index+1];
	  index+=2;
  }
  index-=2;
  sum+=((u16_t)sendbuf[index]<<8)+sendbuf[index+1];
  index+=4;

  for(i=0;i<(datalen/2);i++){
	  sum+=((u16_t)sendbbf[index]<<8)+sendbuf[index+1];
	  index+=2;
  }
  if(datalen%2){
      sum+=((u16_t)sendbbf[index]<<8);
  }
  
  sum = (sum >> 16) + (sum & 0xffff);

  return (~sum & 0xffff);
}

http://www.niftyadmin.cn/n/784060.html

相关文章

如何修改移动设备按钮默认样式

在为移动设备制作网页的过程中&#xff0c;你可能会遇到下述奇怪的现象&#xff1a;当你为一个按钮设置样式&#xff0c;并在浏览器打开模拟器查看效果时&#xff0c;一切都很美好。 但当你使用真机测试时&#xff0c;你的按钮却变成了下面这个样子&#xff1a; 而且即使你使用…

蚂蚁金服Java后台一面

自我介绍 讲一下实习的项目 讲一下实习中你理解最深刻的地方 能说说什么是嵌入式数据库吗 为什么redis的qps没有rocksdb要高 如何设计一个线程池&#xff0c;从操作系统角度去说 java线程有哪几种状态 time waiting和waiting的区别是什么 time waiting和waiting下一个状…

[BZOJ 3932][CQOI2015]任务查询系统

Link: BZOJ 3932 传送门 Solution: 一道比较基础的数据结构题吧&#xff0c;然而一开始我想的还是两个$log$…… 明显看出我们是要对每一个时刻$x$维护各个权值区间内数的个数及数的和&#xff0c;主席树的经典模型 在一开始建树时可以使用前缀数组差分的方式&#xff1a; 对于…

疏漏总结(十一)

什么是Java的快速失败和安全失败&#xff1f; 快速失败&#xff1a;两个线程&#xff0c;A去读一个集合的内容&#xff0c;B去update相同集合的内容&#xff0c;会报ConcurrentModificationException。 原因是&#xff1a;集合框架内部针对每个元素有一个modCount&#xff0c;…

LVM缩小根分区

逻辑卷不是根分区都可以在线扩容和缩小 根分区是可以在线扩容&#xff0c;但不可以在线缩小 Linux系统进入救援模式 依次选择&#xff1a; 欢迎界面 ---------- Rescue installed system Chose a Language ------------- English Keyboard Type --------- us Rescue Method ---…

LinkedList(极客时间)

上次说了链表相关的基础知识。这次总结一些写链表代码的技巧&#xff0c;如果能熟练掌握这些技巧&#xff0c;就可以应对大多数链表的问题。 技巧一&#xff1a;理解引用的含义 事实上&#xff0c;看懂链表的结构并不是很难&#xff0c;但是一旦把它和面向对象的概念套在一起…

c++局部变量在外可用的方法

C的局部变量在作用域结束后&#xff0c;一般都会被回收。如下面这段代码 1 map<a*, b*> _map; 2 3 void fun() 4 { 5 a _a; 6 b _b; 7 _map[&_a] &_b; 8 } 当fun执行完成后&#xff0c;a、b对象都会被析构&#xff0c;所以再访问这两个对象就会出…

学习笔记·堆优化$\mathscr{dijkstra}$

嘤嘤嘤今天被迫学了这个算法……其实对于学习图论来说我内心是拒绝的\(\mathscr{qnq}\) 由于发现关于这个\(\mathscr{SPFA}\)的时间复杂度\(O(kE)\)中的\(k \approx 2\)好像只针对于稀疏图&#xff1f;\(emmm\)想不到时间复杂度居然还有数据分治这一说\(ORZ\) 好的&#xff0c;…