从TCP/IP协议看到IP数据报,看到Checksum的算法描述,不甚了了。
The checksum field is the 16 bit one’s complement of the one’s complement sum of all 16 bit words in the header. ————RFC791
1、怎么算IP Header Checksum?
百度百科里对校验和的解释提到了:1的补码和(one’s complement sum)就是带循环进位(end round carry)的加法,在最后对累加结果取反码。
其实这里讲得很清楚了,但不完全清楚。因为对1的补码和到底怎么算,理解错了。
最开始是按照学数电时对反码加法的理解,即正数的反码等于原码,负数的反码由原码的按位(除了符号位保持为1)取反得到。错。百科最后有附的程序,感觉第10行代码是迷之取反。按这个思路求的结果也不对。
- 找到一个求IP Header Cheaksum的正确方法:
- 把划分出所有的
16bit
数据逐个相加,一旦有进位,就把它加到最低位。 - 最后把结果所有位按位取反。
- 把划分出所有的
- 又找到一个等价的方法:IP数据报首部校验和算法 详细 非代码(接收方检验结果有笔误,但总体写得很棒!)
- 所有数据逐个相加(使用32位的int类型)
- 把高16位右移16位,再与低16位相加。循环该步,直至结果的二进制表示不超过16位。
2、反码究竟是什么?怎么可以这样用?
可行的方法找到了,可为什么是这样的呢?就像这篇博客里说的那样,这些16bit
数据谈不上有正负号,没有什么符号位,一律按位取反,跟加减算数里的用法相去甚远。
首先根据一下表格明确各个概念:
名称 | 英文名称 | 直译名称 |
---|---|---|
反码 | one’s complement< |