- 经验
 - 9 
 - 分贝
 - 0 
 - 家园分
 - 15 
 - 在线时间:
 - 0 小时
 - 最后登录:
 - 2025-10-9
 - 帖子:
 - 8
 - 精华:
 - 0
 - 注册时间:
 - 2013-8-4
 - UID:
 - 935183
  
 
 
 
注册:2013-8-4 
 | 
UDP的校验和需要计算UDP首部加数据荷载部分,但也需要加上UDP伪首部。 
这个伪首部指,源地址、目的地址、UDP数据长度、协议类型(0x11),协议类型就一个字节,但需要补一个字节的0x0,构成12个字节。 
伪首部+UDP首部+数据 一起计算校验和。 
在抓包实验中,也发现过在Linux系统下UDP检验和仅计算在UDP首部的情况,没具体分析是否包含了伪首部,但是肯定没计算数据。在windows系统的接收端上用wireshark抓包,发现校验和是对的。 
 
UDP检验和的计算方法是: 
1.按每16位求和得出一个32位的数; 
2.如果这个32位的数,高16位不为0,则高16位加低16位再得到一个32位的数; 
3.重复第2步直到高16位为0,将低16位取反,得到校验和。 
 
较难和的计算,帖个代码。自己组了个码流,同时也从抓包中把UDP的码流和伪首部直接写到数组里了,两个相互比较,只是为了做个验证。代码也就没有写得那么通用。 
当然,要注意的是,算出来的这个校验和是主机序的,如果要跟抓包中的校验和相比较,转成网络序再对比。 
 
 
- #include <stdio.h>
 
 - #include <unistd.h>
 
 - #include
 
  
- typedef struct {
 
 -     int srcIp;
 
 -     int dstIp;
 
 -     short udp_len;
 
 -     char rsv;
 
 -     char protocol;
 
 -     unsigned short src_port;
 
 -     unsigned short dst_port;
 
 -     unsigned short len;
 
 -     unsigned short check_sum;
 
 -     char data[2];
 
 - } UDPHDR;
 
  
- char arr[100] = {0xc0, 0xa8, 0xd1, 0x80, 0xc0, 0xa8, 0xd1, 0x01, 0x00, 0x0a, 0x00, 0x11, 0x13, 0x88, 0x13, 0x88, 0x00, 0x0a, 0x00, 0x00, 0x61, 0x66};
 
  
- unsigned short check_sum(unsigned short *a, int len);
 
  
- int main()
 
 - {
 
 -     short b = 0;
 
 -     UDPHDR udphdr = {0};
 
  
-     udphdr.srcIp = inet_addr("192.168.209.128");
 
 -     udphdr.dstIp = inet_addr("192.168.209.1");
 
 -     udphdr.udp_len = htons(10);
 
 -     udphdr.protocol = 0x11;
 
 -     udphdr.rsv = 0;
 
 -     udphdr.src_port = htons(5000);
 
 -     udphdr.dst_port = htons(5000);
 
 -     udphdr.len = htons(10);
 
 -     udphdr.check_sum = 0;
 
 -     udphdr.data[0] = 0x61;
 
 -     udphdr.data[1] = 0x66;
 
  
-     b = check_sum((short *)&udphdr, 22);
 
 -     printf("[test ...] b = %04x\n", b & 0xffff);
 
  
-     b = check_sum((short *)arr, 22);
 
 -     printf("[test arr] b = %04x\n", b & 0xffff);
 
  
-     return 0;
 
 - }
 
  
- unsigned short check_sum(unsigned short *a, int len)
 
 - {
 
 -     unsigned int sum = 0;
 
  
-     while (len > 1) {
 
 -         sum += *a++;
 
 -         len -= 2;
 
 -     }
 
  
-     if (len) {
 
 -         sum += *(unsigned char *)a;
 
 -     }
 
  
-     while (sum >> 16) {
 
 -         sum = (sum >> 16) + (sum & 0xffff);
 
 -     }
 
  
-     return (unsigned short)(~sum);
 
 - }
 
  复制代码 
 
 |   
 
  
 |