UDP,全称User Datagram Protocol,用户数据报协议,是TCP/IP四层参考模型中传输层的一种面向报文的、无连接的、不能保证可靠的、无拥塞控制的协议。UDP协议因为传输效率高,常用于即时通信,比如视频/语音聊天,直播等。
1. UDP数据包的格式
用户数据报UDP有两个字段:数据字段和首部字段。首部字段很简单,只有8个字节,由四个字段组成,每个字段的长度都是两字节。各段意义如下:
- 源端口:源端口号。在需要对方回信时选用。不需要时可用全0。
- 目的端口:目的端口号。这在终点交付报文时必须要使用到。
- 长度:UDP用户数据报的长度,其最小值是8(仅首部)。
- 校验和:检测UDP用户数据报在传输中是否有错。有错就丢弃。
![74ad098c6082feda7a91f5f224258703.png](https://i-blog.csdnimg.cn/blog_migrate/7e26bff8e6cf4b1f08207b88d6cf7a4a.jpeg)
2. UDP校验和的计算
UDP的校验和需要计算UDP首部加数据荷载部分,但也需要加上UDP为首部。这个为首部指,源地址、目的地址、UDP数据长度、协议类型(0x11),协议类型就一个字节,但需要补一个字节的0x0,构成12个字节。伪首部+UDP首部+数据一起计算校验和。
UDP检验和的计算方法是:
- 按每16位求和得出一个32位的数;
- 如果这个32位的数,高16位不为0,则高16位加低16位再得到一个32位的数;
- 重复第2步直到高16位为0,将低16位取反,得到校验和。
3. UDP校验和计算方法的Java实现
一个实际例子:
keyhex源IP地址0x0aaa, 0x3bbf目的IP地址0xd20e, 0x960d协议类型0x0011UDP长度0x001c源端口0xd123目的端口0x2742长度0x001c校验和0x285c(用于验证)UDP数据0x0000, 0x6c41, 0x5661, 0x0000, 0x0e00, 0xf8b6, 0xd401, 0x9313, 0x0000, 0x0000, 0x0000
Java实现:
public class CheckSumDemo { public static void main(String[] args) { /** * 源IP * 目的IP * 协议类型 * UDP数据长度 * 源端口 * 目的端口 * UDP数据 * UDP数据 */ int[] udp = { 0x0aaa, 0x3bbf, 0xd20e, 0x960d, 0x0011, 0x001c, 0xd123, 0x2742, 0x001c, 0x0000,0x6c41,0x5661,0x0000,0x0e00,0xf8b6,0xd401,0x9313,0x0000,0x0000,0x0000 }; int checkSum = 0x285c; String s = udpCheckSum(udp); System.out.println(s); System.out.println(Integer.toHexString(checkSum).equals(s)); } public static String udpCheckSum(int[] nums) { int res = 0; for (int num : nums) { res += num; if (res >>> 16 != 0) { res = (res >>> 16) + (res & 0xffff); } } return Integer.toHexString(~res).substring(4); }}
结果输出:
285ctrue