Python 简易实现二进制反码求和

参考链接

  • 二进制反码求和
  • UDP 检验和的回卷是什么意思?

Python 计算 UDP 检验和

目录

1. 前言说明
2. 例子分析
3. 相关代码
4. 结果展示
5. 心得总结

一、前言说明 ↶

在看完教材 5-50 题目的习题解答,稍微懂了一点二进制反码求和。手算总是觉得很容易出错,用程序帮我们计算,尽最大可能减少计算错误的发生。所以,我想用 Python 简易实现二进制反码求和计算 UDP 检验和的过程,顺便巩固和复习一些 Python 语法。

二、例子分析 ↶

这里把题目和较详细解答过程直接贴在这里【思路 + 过程】
50. 把教材上的图 5-7 计算 UDP 检验和的例子自己具体演算一下,看是否能够得出书上的计算结果。
        可以使用两种方法进行二进制反码求和的运算。一种方法是把这 14 行的 16 位数据一起从低位到高位逐位相加。另一种方法是把这 14 行的 16 位数据两行两行地相加(即二进制反码求和)

我们这里使用后一种方法,这里要相加 13 次。
第 1 行和 第 2 行相加,得 10100001 01111011
再和第 3 行相加,得 1 01001100 011111110。请注意,最左边(最高位)的 1 是进位得到的 1,这要和最低位相加。因此和第 3 行相加后,得 01001100 01111111。最低位的 1 就是由最高位的进位得到的。这叫做 “回卷”。
再和第 4 行相加,得 01011010 10001010。
再和第 5 行相加,得 01011010 10011011。
再和第 6 行相加,得 01011010 10101010。
再和第 7 行相加,得 01011110 11101001。
再和第 8 行相加,得 01011110 11110110。
再和第 9 行相加,得 01011111 00000101。
第 10 行是全 0,不用再计算相加。
再和第 11 行相加,得 10110011 01001010。
再和第 12 行相加,得 00000110 10011111。这里的最低位的 1 由最高位的进位回卷得到的。
再和第 13 行相加,得 01001111 11101101。
再和第 14 行相加,得 10010110 11101101。这就是二进制反码求和的结果。把这个结果求反码(1 换成 0 而 0 换成 1),得出:01101001 00010010。这就是应当写在检验和字段的数。和书上给出的结果是一致的。

        UDP 用户数据报传送到接收端后,再进行检验和计算。这就是把收到的 UDP 用户数据报连同伪首部(以及可能的填充全零字节)一起,按二进制反码求这些 16 位字的和。当无差错时其结果应当全 1。否则就表明有差错出现,接收方就应丢弃这个 UDP 用户数据报(也可以上交应用层,但附上出现差错的警告)。

三、相关代码 ↶

简易实现:

def checkBits(raw_data, bits):
    # 检查原来的数据是否满足 bits 位
    for (a, b) in enumerate(raw_data):
        if len(b) != bits:
            print("NO.{}: {}".format(a+1, b))
            return False
    return True

def format_print(string, bits):
    # 对按bits字符串切片,加空格
    length = len(string)
    new_list = []
    for i in range(bits, length+1, bits):
        new_list.append(string[i-bits:i])
    remain = length % bits
    if remain != 0:
        new_list.append(string[-remain:])
    return ' '.join(new_list)
    
class Binary_complement_sum():
    def __init__(self, raw_bits, bits):
        self.raw_bits = raw_bits
        self.bits = bits
        self.total = ''
        self.inv_dict = {'0': '1',
                                  '1': '0'}
    def calculate(self):
        # 用二进制反码求和的方法加起来
        total = self.raw_bits[0]
        for i in self.raw_bits[1:]:
            total = str(bin(int(total, 2) + int(i, 2)))[2:]
            if len(total) > self.bits:
                total = str(bin(int(total[-self.bits:], 2) + 1))[2:]
        self.total = total
        return total
            
    def inverse(self):
        # 求它的反码
        inv_code = ''
        for i in self.total:
            inv_code += self.inv_dict[i]

        return inv_code


if __name__ == '__main__':

    raw_data = ['1001100100010011',
               '0000100001101000',
               '1010101100000011',
               '0000111000001011',
               '0000000000010001',
               '0000000000001111',
               '0000010000111111',
               '0000000000001101',
               '0000000000001111',
               '0000000000000000',
               '0101010001000101',
               '0101001101010100',
               '0100100101001110',
               '0100011100000000']
    bits = 16

    # 检查位数是否满足 bit 位
    if checkBits(raw_data, bits):
        bin_com_sum = Binary_complement_sum(raw_data, bits)
        total = bin_com_sum.calculate()
        inv_code = bin_com_sum.inverse()
        print("二进制反码运算求和:{}".format(format_print(total, 8)))
        print("将得出的结果求反码:{}".format(format_print(inv_code, 8)))
    else:
        print("请检查原始数据是否输入正确!")
        

四、结果展示 ↶

    raw_data = ['1001100100010011',
    '0000100001101000',
    '1010101100000011',
     '0000111000001011',
     '0000000000010001',
     '0000000000001111',
     '0000010000111111',
     '0000000000001101',
     '0000000000001111',
     '0000000000000000',
     '0101010001000101',
     '0101001101010100',
     '0100100101001110',
     '0100011100000000']

结果:

# 上面例子的检验
二进制反码运算求和:10010110 11101101
将得出的结果求反码:01101001 00010010
>>> 

    raw_data = ['1001100100010010',
    '0000100001101001',
    '1010101100000010',
    '0000111000001010',
    '0000000000010001',
    '0000000000001111',
    '0000010000111111',
    '0000000000001101',
    '0000000000001111',
    '0000000000000000',
    '0101010001000101',
    '0101001101010100',
    '0100100101001111',
    '0100011100000000']

结果:

二进制反码运算求和:10010110 11101100
将得出的结果求反码:01101001 00010011
>>> 

例题来自:二进制反码求和举例

五、心得总结 ↶

实验的例子太少,导致没办法验证代码的可靠性。但是用教材上的例子实验,结果表明没有问题。通过对题目解答的了解和阅读,按二进制反码求和开始懂一些了。边学变练,记得才牢。好记性不如烂笔头。ヾ(◍°∇°◍)ノ゙ 加油吧

点我回顶部 ☚

 
 
 
 
 
 
 
Fin.

你可能感兴趣的:(网络通信学习)