校验和算法

IP/ICMP/IGMP/TCP/UDP等协议的校验和算法都是相同的,采用的都是将数据流视为16位整数流进行重复叠加计算。为了计算检验和,首先把检验和字段置为0。然后,对有效数据范围内中每个16位进行二进制反码求和,结果存在检验和字段中,如果数据长度字节数为奇数,那么就在末尾则填充0。当收到数据后,同样对有效数据范围中每个16位数进行二进制反码的求和。由于接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果首部在传输过程中没有发生任何差错,那么接收方计算的结果应该为全0或全1(具体看实现了,本质一样) 。如果结果不是全0或全1,那么表示数据错误。

什么是二进制反码求和(1的补码)
对一个无符号的数,先求其反码,然后从低位到高位,按位相加,有溢出则向高位进1(跟一般的二进制加法规则一样),若最高位有进位,则向最低位进1。
首先这里的反码好像跟我们以前学的有符号数的反码不一样(即正数的反码是其本身,负数的反码是在其原码的基础上,符号位不变,其余各位取反),这里不分正负数,直接每个位都取反!
上面加粗的那句是跟我们一般的加法规则不太一样的地方:最高位有进位,则向最低位进1。确实有些疑惑,为什么要这样做呢?仔细分析一下(为了方便说明,以 4bit二进制反码求和举例),上面的这种操作,使得在发生加法进位溢出时,溢出的值并不是10000,而是1111。也即是当相加结果满1111时溢出,这样也可以说明为什么0000和1111都表示0了(你同样可以发现,任何数与这两个数做二进制反码求和运算结果都是原数,这恰好符合数0的加法意义)。
另外关于二进制反码求和运算需要说明的一点是,先取反后相加与先相加后取反,得到的结果是一样的!,事实上我们的编程算法里,几乎都是先相加后取反。

1的补码(相加和补取)
猜测是计算机相关语言.请参考这两段文字:
It is the 1’s complement of the 1’s complement sum of all the 16-bit words in the TCP header and data.
这是关于TCP头部校验和字段(checksum field)的说明.句中的complement意思为“补码”.对于学习计算机科学的人来说,补码不算什么新鲜,现在新鲜的是这篇英语文章出现的是“1’s complement” ,翻译出来应该是“1的补码”,对于这个笔者以前也没有碰到过,到网上查吧!网上查询的结果,“1’s complement”关键字出现的不少,但都是英文关键字,没有对应的中文翻译与解释,所以先看英语的,最后自己做解释吧.
补码:补码是计算机中二进制数表达负数的办法,这样可以在计算机中把两个数的减法变成加法.补码形式有1的补码和2的补码,其中1的补码用在IP、TCP的校验和中;平时学生在计算机科学中学习的补码是2的补码(即正数的补码和原码相同,负数补码按原码相应的正数按位取反再加1).
只是平时中文教材及中文翻译的书中,对此并不多加解释,一律翻译作补码.比如《Computer Network》(Andrew S.Tanenbaum )在中国的翻译版《计算机网络》(清华大学出版社)对于TCP头部的校验和是这样翻译的:
(原文)The checksum algorithm is simply to add up all the 16-bit words in one's complement and then to take the one's complement of the sum.
(译文)校验和的算法是简单地将所有16位字以补码形式相加,然后再对相加和取补.
仔细对比一下本文最上部笔者所碰到的句子,和刚才这个句子意思是一样的.这个没有注明是1的补码,翻译时只是以“补码”说明,也许译者并不想在这里多费口舌,因为说明1的补码实在是一个比较麻烦的事情,笔者在这里翻译时还是把“1的补码”给翻译出来了,以让大家注意这个1的补码并不是平常学的那个2的补码.
笔者只是在此讨论翻译,不是在讨论补码.1的补码较复杂,如果有兴趣,可以上网查找 RFC1071 ,这是TCP校验和权威的官方说明.
发布了40 篇原创文章 · 获赞 36 · 访问量 23万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章