Python 计算 UDP 检验和 目录

1. 前言2. 分析
3. 代码
4. 结果
5. 总结

一、前言 ↶

IP 头部校验、UDP 校验与 TCP 校验方法基本一致,这里用参考链接一里面的 UDP 数据包来了解 UDP 检验和的计算。

二、分析 ↶

python 校验sql python 校验和_二进制反码求和


UDP 计算检验和的方法和计算 IP 数据报首部检验和的方法相似。但不同的是:IP数据包的检验和只检验 IP 数据报的首部,但 UDP 的检验和是把首部和数据部分一起检验。

  1. 先得出 UDP 校验和部分
    UDP 校验和部分 = 伪首部(12 字节) + UDP 首部(8 字节)+ 数据(n 个字节)
    伪首部(12 字节) = 源 IP 地址(4 字节) + 目的 IP 地址(4 字节)+ 0x00(1 字节)+ 协议号(1 字节)+ UDP 长度(2 字节)
    将 UDP 校验和部分拼出来后,将检验和置为 0 。将校验部分看成许多 16位的字串接起来的。若 UDP 用户数据部分不是偶数个字节,则要填充一个全 0 字节(但此字节不发送)。
  2. 按 二进制反码计算 出这些 16 位字的和
  3. 当无差错时,其结果应为全 1。否则就表明有差错出现,接收方就应该丢弃这个 UDP 数据报(也可以上交给应用层,但附上出现了差错的警告)
三、代码 ↶
class Udp_check():
    def __init__(self, IP_content):
        self.IP_content =  IP_content
        self.IP_header_len = 20 #IP头部20字节
        self.check_content = []  #UDP校验和部分
        # UDP校验和部分 = UDP伪首部 + UDP内容(UDP首部 + UDP数据部分)
        
    def add_udp_pseudo_header_content(self):
        # UDP伪首部 = 源IP地址 + 目的IP地址 + 0x00 +协议字段 + UDP长度
        
        #IP源地址为IP报文的13、14、15、16字节,即伪首部的源IP地址字段
        self.check_content.append(self.IP_content[12])
        self.check_content.append(self.IP_content[13])
        self.check_content.append(self.IP_content[14])
        self.check_content.append(self.IP_content[15])

        #IP目的地址为IP报文的17、18、19、20字节,即伪首部的目的IP地址字段
        self.check_content.append(self.IP_content[16])
        self.check_content.append(self.IP_content[17])
        self.check_content.append(self.IP_content[18])
        self.check_content.append(self.IP_content[19])

        #UDP伪首部的第三个字段,为0x00
        self.check_content.append(0x00)
        
        #协议类型是IP报文的第10字节,即伪首部的协议类型字段
        self.check_content.append(self.IP_content[9])

        #UDP数据长度是UDP报文中的第5、6字节,伪首部的长度字段

        self.check_content.append(self.IP_content[self.IP_header_len + 4])
        self.check_content.append(self.IP_content[self.IP_header_len + 5])

    def add_udp_content(self):
        #udp内容的长度
        udp_content_len = len(self.IP_content) - self.IP_header_len
        #往校验部分添加udp内容
        for i in range(udp_content_len):
            self.check_content.append(self.IP_content[self.IP_header_len + i])

    def set_and_fill_zero(self):
        self.check_content[18] = 0    #把原来的校验和设置为0
        self.check_content[19] = 0

        if len(self.check_content) % 2 == 1: #整个报文长度为奇数需要补充0
            self.check_content.append(0x00)


    def check_process(self):
        data_sum = []
        
        #先需要将前后二个数合并成16位长度的16进制的数
        for num in range(0, len(self.check_content), 2):
            #如果转换为16进制后只有1位需要高位补0操作,用zfill方法
            part1 = str(hex(self.check_content[num]))[2:].zfill(2)
            part2 = str(hex(self.check_content[num+1]))[2:].zfill(2)
            part_all = part1 + part2
            data_sum.append(int(part_all, 16))
##        print(data_sum)

        sum_total = sum(data_sum) #计算所有数的和
        sum_total_hex = str(hex(sum_total))[2:] #16进制化
        sum_total_hex_len = len(sum_total_hex) #取得字节长度

        if sum_total_hex_len > 4: #求和的结果大于2个[字节16位]的话,分割成2个2字节16位数
            part1 = int(sum_total_hex[: sum_total_hex_len - 4], 16) #分割第一、二字节的十六进制数字,转换为10进制
            part2 = int(sum_total_hex[sum_total_hex_len - 4: ], 16) #分割第三、四字节的十六进制数字,转换为10进制
            part_all = part1 + part2
        else:
            part_all = sum_total

        last_check_sum = str(hex(65535 - part_all))[2:]    #二个字节的十六进制数之和取反
        return sum_total_hex, last_check_sum
    
            
    def run(self):
        self.add_udp_pseudo_header_content()
        self.add_udp_content()
        check1 = str(hex(self.check_content[18]))[2:]
        check2 = str(hex(self.check_content[19]))[2:]
                  
        print("检验和:0x{0}{1}".format(check1, check2))

        self.set_and_fill_zero()
        print('需要计算的UDP校验和内容为:{}'.format((self.check_content)))
        ## UDP校验和部分准备完成

        sum_total_hex, last_check_sum = self.check_process()
        print("sum_total_hex: 0x{}".format(sum_total_hex))
        print("检验和:0x{0}".format(last_check_sum))

        temp = hex((int(sum_total_hex, 16) >> 16) + (int(sum_total_hex, 16) & 0xffff))
        print("(0x{0} >> 16) + (0x{0} & 0xffff) = {1} ".format(sum_total_hex, temp))

        temp2 = hex(int(temp, 16) + int('0x' + check1 + check2, 16))
        print("{0} + 0x{1}{2} = {3}".format(temp, check1, check2, temp2))
        
        

if __name__ == '__main__':
    IP_content_hex = ['45', '00', '01', '23', '7f', '1e', '00', '00', '40', '11', 'd5', '85', '0a', '08', '88', '17',
    '0a', '08', '88', 'ff', 'd6', '83', 'd6', '83', '01', '0f', '5f', '62', '00', '73', '68', '79',
    '79', '79', '66', '2d', '67', '75', '74', '69', '6e', '67', '74', '00', '00', '00', '00', '00',
    '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '20', '5f', '27', '02',
    '00', '00', '00', '00', '30', 'b4', '9f', '06', '00', '00', '00', '00', '33', '27', '00', '00',
    '00', '00', '00', '00', '10', '5f', '27', '02', '00', '00', '00', '00', 'c0', '04', '6e', '05',
    '00', '00', '00', '00', '7c', '6a', '7a', '70', '00', '00', '00', '00', '98', 'a3', 'da', '6f',
    '00', '00', '00', '00', '59', 'b8', '9f', '06', '00', '00', '00', '00', '00', '00', '00', '00',
    '00', '00', '00', '00', '70', '97', 'da', '04', '00', '00', '00', '00', 'a4', 'b4', '9f', '06',
    '00', '00', '00', '00', 'c0', 'b4', '9f', '06', '00', '00', '00', '00', 'a8', 'd9', '7a', '7b',
    '61', '63', '36', '35', '64', '66', '64', '62', '2d', '36', '32', '37', '34', '2d', '34', '65',
    '65', '34', '2d', '62', '63', '64', '64', '2d', '34', '35', '62', '36', '61', '62', '63', '63',
    '37', '31', '36', '39', '7d', '00', '00', '00', '00', '00', '00', '00', '01', '00', '00', '00',
    '00', '00', '00', '00', 'a0', 'b4', '9f', '06', '00', '00', '00', '00', '00', '00', '00', '00',
    '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00',
    '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00',
    '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00',
    '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '35',
    'a5', '8a', 'f3']
    print("IP_content:{}".format(len(IP_content_hex)))
    
    IP_content_dec = [int(i, 16) for i in IP_content_hex] #十进制化
    udp_check = Udp_check(IP_content_dec)
    udp_check.run()
四、结果 ↶

IP_content_hex = ['45', '00', '01', '23', '7f', '1e', '00', '00', '40', '11', 'd5', '85', '0a', '08', '88', '17',
    '0a', '08', '88', 'ff', 'd6', '83', 'd6', '83', '01', '0f', '5f', '62', '00', '73', '68', '79',
    '79', '79', '66', '2d', '67', '75', '74', '69', '6e', '67', '74', '00', '00', '00', '00', '00',
    '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '20', '5f', '27', '02',
    '00', '00', '00', '00', '30', 'b4', '9f', '06', '00', '00', '00', '00', '33', '27', '00', '00',
    '00', '00', '00', '00', '10', '5f', '27', '02', '00', '00', '00', '00', 'c0', '04', '6e', '05',
    '00', '00', '00', '00', '7c', '6a', '7a', '70', '00', '00', '00', '00', '98', 'a3', 'da', '6f',
    '00', '00', '00', '00', '59', 'b8', '9f', '06', '00', '00', '00', '00', '00', '00', '00', '00',
    '00', '00', '00', '00', '70', '97', 'da', '04', '00', '00', '00', '00', 'a4', 'b4', '9f', '06',
    '00', '00', '00', '00', 'c0', 'b4', '9f', '06', '00', '00', '00', '00', 'a8', 'd9', '7a', '7b',
    '61', '63', '36', '35', '64', '66', '64', '62', '2d', '36', '32', '37', '34', '2d', '34', '65',
    '65', '34', '2d', '62', '63', '64', '64', '2d', '34', '35', '62', '36', '61', '62', '63', '63',
    '37', '31', '36', '39', '7d', '00', '00', '00', '00', '00', '00', '00', '01', '00', '00', '00',
    '00', '00', '00', '00', 'a0', 'b4', '9f', '06', '00', '00', '00', '00', '00', '00', '00', '00',
    '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00',
    '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00',
    '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00',
    '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '00', '35',
    'a5', '8a', 'f3']

结果:

IP_content:291
检验和:0x5f62
需要计算的UDP校验和内容为:[10, 8, 136, 23, 10, 8, 136, 255, 0, 17, 1, 15, 214, 131, 214, 131, 1, 15, 0, 0, 0, 115, 104, 121, 121, 121, 102, 45, 103, 117, 116, 105, 110, 103, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 95, 39, 2, 0, 0, 0, 0, 48, 180, 159, 6, 0, 0, 0, 0, 51, 39, 0, 0, 0, 0, 0, 0, 16, 95, 39, 2, 0, 0, 0, 0, 192, 4, 110, 5, 0, 0, 0, 0, 124, 106, 122, 112, 0, 0, 0, 0, 152, 163, 218, 111, 0, 0, 0, 0, 89, 184, 159, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 151, 218, 4, 0, 0, 0, 0, 164, 180, 159, 6, 0, 0, 0, 0, 192, 180, 159, 6, 0, 0, 0, 0, 168, 217, 122, 123, 97, 99, 54, 53, 100, 102, 100, 98, 45, 54, 50, 55, 52, 45, 52, 101, 101, 52, 45, 98, 99, 100, 100, 45, 52, 53, 98, 54, 97, 98, 99, 99, 55, 49, 54, 57, 125, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 160, 180, 159, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 165, 138, 243, 0]
sum_total_hex: 0x19a084
检验和:0x5f62
(0x19a084 >> 16) + (0x19a084 & 0xffff) = 0xa09d 
0xa09d + 0x5f62 = 0xffff

IP_content_hex = ['45', '00', 
    '00', '54', '00', '00', '40', '00', '37', '11', '6c', 'ea','db', '85', '28', '25', 'c0', 'a8',
    '12', '5c', '1f', '40', '0f', 'a0', '00', '40', '71', '2a', '02', '0f','19', '00', '02', '2e',
    'eb', '3f', '34', '21', '51', 'c4', 'b6', 'cb', '12', '05', 'a3', '24','b4', '11', 'a8', 'd3',
    '93', 'd2', 'cf', 'ac', '48', 'b7', '98', 'd4', '83', '03', '1a', 'ae','14', '11', 'ed', '24',
    'bf', 'c8', '6f', 'db', '9a', 'fa', 'd8', 'c6', '2a', 'ca', '21', '08','a2', 'bd', '25', '8b',
    '96', '03']

结果:

IP_content:84
检验和:0x712a
需要计算的UDP校验和内容为:[219, 133, 40, 37, 192, 168, 18, 92, 0, 17, 0, 64, 31, 64, 15, 160, 0, 64, 0, 0, 2, 15, 25, 0, 2, 46, 235, 63, 52, 33, 81, 196, 182, 203, 18, 5, 163, 36, 180, 17, 168, 211, 147, 210, 207, 172, 72, 183, 152, 212, 131, 3, 26, 174, 20, 17, 237, 36, 191, 200, 111, 219, 154, 250, 216, 198, 42, 202, 33, 8, 162, 189, 37, 139, 150, 3]
sum_total_hex: 0xe8ec7
检验和:0x712a
(0xe8ec7 >> 16) + (0xe8ec7 & 0xffff) = 0x8ed5 
0x8ed5 + 0x712a = 0xffff
五、总结 ↶

主要写了使用 Python 计算 UDP 检验和