二进制反码求和运算

UDP协议的校验和的计算

  其实本质上来说这个计算原理还是不难的,就是一个二进制反码求和运算,具体来说就是:

                                          0+0=0;0+0=0

                                          1+0=0+1=1;1+0=0+1=1

                                          1+1=10;1+1=10

  其中10中的1加到了下一列去,如果是最高列的1+1,那么得到的10留下0,1移到最低列,与最低位再做一次二进制加法即可。

  在谢老师的这本书里,讲到的是一个15字节的UDP数据在发送方怎么进行数据的检验,然后列出了一个二进制的竖式并给出一个结果,然而并没有讲述是怎么计算出来的。经过我不断的努力,终于把二进制计算的过程整个写出来了。之前在数计院上课的时候,老师讲过一个较为之简单的十六进制计算法,对比之下确实是简单很多。好了,先上图。

谢老师在课本里面给出的题目是这样子的。

二进制版
1001 1001 0001 0011 //伪首部源IP地址前16位
0000 1000 0110 1000 //伪首部源IP地址后16位
1010 1011 0000 0011 //伪首部目的IP地址前16位
0000 1110 0000 1011 //伪首部目的IP地址后16位
0000 0000 0001 0001 //伪首部UDP协议字段代表号17,前面8位是填充0
0000 0000 0000 1111 //伪首部UDP长度字段
0000 0100 0011 1111 //UDP头部源IP地址对应的进程端口号
0000 0000 0000 1101 //UDP头部目的IP地址对应的进程端口号
0000 0000 0000 1111 //UDP头部UDP长度字段
0000 0000 0000 0000 //UDP头部UDP检验和
0101 0100 0100 0101 //数据字段
0101 0011 0101 0100 //数据字段
0100 1001 0100 1110 //数据字段
0100 0111 0000 0000 //数据字段+填充0字段
    
十六进制版
9913        //伪首部源IP地址前16位
0868        //伪首部源IP地址后16位
AB03        //伪首部目的IP地址前16位
0E0B        //伪首部目的IP地址后16位
0011        //伪首部UDP协议字段代表号17,前面8位是填充0
000F        //伪首部UDP长度字段
043F        //UDP头部源IP地址对应的进程端口号
000D        //UDP头部目的IP地址对应的进程端口号
000F        //UDP头部UDP长度字段
0000        //UDP头部UDP检验和
5445        //数据字段
5354        //数据字段
494E        //数据字段
4700        //数据字段+填充0字段

 在二进制版中,是不可以直接从右边第一列开始做竖式相加的,不要说十进制的竖式相加,二进制的竖式相加都做不到。

      正确的做法是:
      (1) 让第一行和第二行做二进制反码运算。
      根据上述的规则,当碰到1+1=10时,在左邻侧一列下面写个小1(类似以前做十进制进位加法),然后侧列进行二进制反码运算得出一个数,如果没有进位,就继续与刚才的进位做二进制反码运算,如果有进位,则先把进位的小1写在相邻高侧列的下方,取个位来与其相加。有进位的只有1+1=10的情况,0不论加什么进位都不会有进位,而如果第一次计算没有进位时,只有产生1的情况下才会有进位,总而言之,对于每一列,都只会有至多一次的进位,所以不用担心进位会跨列的问题。这样子做要注意的就是不要写错数字了,比如我自己在写这张纸之前已经打过两次草稿了,然而还是会写错。
      对于高位有1的情况,就是把1挪到最低位,再做一次二进制反码计算,本质来说就是取补码。
      (2) 将第一行和第二行的结果与第三行做二进制反码计算,以此类推。
      (3) 运算结果取反,得到校验和。

      在十六进制版中,运算量会大大减小,主要的计算步骤如下:
      (1) 从右边第一列开始,按照十进制来计算第一列的值。
      在这里第一列算出来是107,写成8位二进制就是01101011。
      (2) 根据算出来的结果分成两部分,左边的4位化成十进制,作为下一列进位时加的数,右边4位化成16进制,作为第一列的结果。
      这里就是610B16,图片误算成D,6作为下一列运算时要加上的对象,B作为第一列的结果。
      (3) 十进制计算第二列的结果,加上第一列得到的进位得到第二列的一个十进制数字,化为二进制,根据第二步来进行判断,依次类推。
      在这里第二列算到的是24,加上6就是30,化为8位二进制就是00011110,也就是1E,第二列的结果为1,第三列的十进制进位为1。接着可以算到第三列的结果为6,十进制进位为4。
      (4) 最高位算出最后的十进制结果后,化为二进制时,右边4位作为最终结果,左边4位移入下一列,用上一步得到的结果96EB,加上0010,得到最后结果,这里图片的最后一步写错了,不应该舍弃。
      最后能得到结果为96ED。
      (5) 结果取反,得到校验码。
      校验码为6912。

      好了这次先针对这个特定的问题提出了解决方案,有时间要好好整理下关于计算机的原码、反码和补码的知识。

猜你喜欢

转载自blog.csdn.net/qq_36171263/article/details/100335730