在巨著《TCP/IP详解1》中有这样一句话:“ICMP,IGMP,UDP and TCP all use the same checksum algorithm”。的确,检验和算法在TCP/IP协议族中大同小异。其过程大致都是:接收方通过判断检验和是否一致,进一步判断该数据包头部传输过程中是否丢失或者被污染了。本文将以IP协议首部(见下图)为例简单介绍检验和算法:

    

    简单地说,检验和是一个16位字段,即上图中16位首部检验和。通过设置该字段取值,将该IP首部是否完整的信息携带其中。还记得以前的信封吗,在包好的信封背面,往往有一个红泥印,收信人常常通过红泥印来判断信封是否曾被人打开。而检验和字段就是IP数据包首部的“红泥印”。

    

    

    设置检验和或许有许多方法,目前,最为流行的一种方法是这样的。首先在发送端计算检验和,将其与IP数据包一起发出,接收端对该数据包头部进行相应的处理,得到检验和大小,从而判断数据包头部是否完整。

    检验和算法可以分成两步来实现。首先在发送端,有以下三步:

  1. 把即将发送的IP头部中的检验和设置为0,然后以16位为一个间隔,将IP头部分成许多个16位的字段;
  2. 将第1步获得的所有字段进行二进制相加求和;
  3. 把最终结果取反,就得到检验和,再将该值填充到IP头部。

    其次在接收端,也有相应的三步:

  1. 把接收到的IP头部分成16位一个间隔的字段集合;
  2. 所有字段进行二进制相加求和;
  3. 将最终结果取反,判断该结果是否为0,若为0,则说明检验和正确,若不为0,则协议栈会丢掉这个包。(你没看错,这一步还是要取反)

   上面的步骤,很抽象,也很无聊。一起来看一个例子。

  0                       1                        2                        3

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 (32位,4字节)

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 4  | 5  |   0    |     28       |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|        1      |   0   |  0     |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|    4  |    17  |    0(checksum)      |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|                       10.12.14.5                                                                  |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|                    12.6.7.9                                                                        |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    这是典型的IP报头,其中各个字段的值都已经设置了。检验和先设为0。

    使用二进制或者十六进制来计算它的检验和。

      4,5,0--> 0100 0101 0000 0000

      28 --> 0000 0000 0001 1100

      1  -->  0000 0000 0000 0001

      0,0-->0000 0000 0000 0000

      4,17-->0000 0100 0001 0001

      0    -->0000 0000 0000 0000

      10.12-->0000 1010 0000 1100

      14.5-->0000 1110 0000 0101

      12.6-->0000 1100 0000 0110

      7.9-->0000 0111 0000 1001

      和-->0111 0100 0100 1110(744E,十六进制)

    对上面的求和取反,就得到检验和,为8BB1,那么就在IP首部将16位检验和设置为8BB1。

    假设数据包是完整的,接收端相应地进行操作,8BB1+744E,就得到了FFFF,取反则为0,所以验证了数据包没有被污染。

    这一切似乎都是我在瞎捣弄,所以这么巧。那么使用wireshake抓包软件来做个试验吧,随机抓取一个接收端的包,按照上面所说的方法验证其中的检验和,图中最下方蓝色16进制字段就是IP报头,共20个字节。

    需注意,因为是接收包,已经设置了检验和,即ab7e,在最初发送这个包时,计算检验和,这个字段设置为0000,计算完成后,再将结果ab7e填充到这个字段。其原理可以表示为下图,图中T为除了checksum,IP数据包首部其他的字段和,即检验和算法步骤2的结果:

    再来看看代码,网上到处都有这份代码,我就随便copy了,汇编代码请参考附录链接1:

USHORT checksum (USHORT *buffer,int size){Unsigned long cksum=0;/*32位长整数,检验和被置为0*/While (size>1){Cksum +=*buffer++;size -=sizeof(USHORT);}If (size) /*处理剩余下来的字段,这些字段皆小于16位*/{Cksum +=*(UCHAR *) buffer;}/*将32位转换为16位,高16位与低16位相加*/While (cksum>>16)Cksum = (cksum>>16) + (cksum & 0xffff);Return (USHORT) (~cksum);}

    看完代码后,你可能会有一个疑惑,代码中为什么要将cksum设置为unsigned long (32位)而非16位呢?这要回到刚才wireshake那张图来解释,那张图里有一个陷阱,你可能没注意。按前面步骤仔细计算图中检验和,会发现一个奇怪的地方。该图中所有16位字段相加,最后结果是2547F(16进制),已经超出了16位,如何处理这个超出的数’2’呢?难道上面计算检验和的方法是错误的?好吧,对不起,为了简单起见,在前文我避开了一个知识点:二进制反码计算。细节不再赘述,请参考附录链接2。在此处,我们这样处理,将溢出的“2”与最末端“F”相加,得到5481,将5481与ab7e相加,就是FFFF,取反,正好为0,说明这个数据包没有“被人动过手脚”,这样它才能被wireshake抓到,否则,就会被协议栈丢弃。同时,这也可以解释为什么将cksum变量设置为32位,是用高16位存储溢出的位值,并将溢出位与cksum低16位相加。

    提一个问题,如果接收方已经接受到一个文件的部分数据,但其中有一个ip数据包由于检验和不对而被丢弃,那么接收方后续将如何处理已经接收到的数据呢?

    检验和只是差错检验的一种,而且也可能出错。所以还有许多其他的方法以及补充措施,比如奇偶检验,循环冗余检验(CRC),tcp协议自身的检错功能。感兴趣的话,可以阅读RFC1071,请参考附录链接3。

附录:

链接3:http://www.faqs.org/rfcs/rfc1071.html

链接2:http://blog.chinaunix.net/uid-26758209-id-3146230.html

链接1:http://blog.csdn.net/chenlong12580/article/details/7354037

参考书1:《TCP/IP协议族》 BehrouzA.Forouzan著,谢希仁审校

参考书2:《TCP/IP详解1》Richard Stevens

【TCP/IP】检验和算法相关推荐

  1. TCP/IP 校验和算法简介

    1. 前言 校验和计算是NAT功能和内容修改功能的基本功,这些操作进行后都需要修改数据头中的校验和. 2. 16位校验和计算 2.1 基本原理 IP/ICMP/IGMP/TCP/UDP等协议的校验和算 ...

  2. 万字长文,一文搞懂TCP/IP和HTTP、HTTPS

    来自:非科班的科班 TCP/IP概念 TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现 ...

  3. TCP/IP 协议栈及 OSI 参考模型详解--云平台技术栈04

    导读:之前发布了云平台技术栈(ps:点击可查看),本文主要说一下其中的tcp/ip和网络! 来源:王东裕 http://wangdy.blog.51cto.com/3845563/1588379 OS ...

  4. 《TCP/IP详解卷1:协议》第6章 ICMP:Internet控制报文协议-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

  5. TCP/IP详解--第十一章

     第11章 UDP:用户数据报协议 11.1  引言   UDP是一个简单的面向数据报的运输层协议:进程的每个输出操作都正好产生一个  UDP .   数据报,并组装成一份待发送的  I P 数据报 ...

  6. TCP/IP详解--第十章

    第10章 动态选路协议 10.1   引言   在前面各章中,我们讨论了静态选路.在配置接口时,以默认方式生成路由表项(对于 直接连接的接口),并通过 route命令增加表项(通常从系统自引导程序文件 ...

  7. TCP/IP详解--第六章

    第6章 ICMP:Internet控制报文协议 6.1   引言   I C M P 经常被认为是 I P 层的一个组成部分.它传递差错报文以及其他需要注意的信息. ICMP报文通常被 IP 层或更高 ...

  8. TCP/IP详解--第三章

    第3章 IP:网际协议 3.1    引言 IP是TCP/IP协议族中最为核心的协议.所有的 TCP.UDP.ICMP及IGMP数据都以 IP数据 报格式传输(见图 1-4).许多刚开始接触 TCP/ ...

  9. TCP/IP 详解卷一 - TCP CWR、ECE、URG、ACK、PSH、RST、SYN、FIN控制位

    from:https://blog.csdn.net/u012243115/article/details/43487461 2015年02月04日 15:56:32 阅读数:1464 TCP 和 U ...

最新文章

  1. mac android 真机调试
  2. 瑞德西韦重症用药结果再曝光,上百名重症一周内好转,股价大涨19%
  3. 中望CAD 2021中文版
  4. Qt Creator快捷键
  5. 数据存储之 SQLite 数据库操作(三)
  6. Tree Cutting POJ - 2378(树形DP)
  7. curl 没有到主机的路由_安装RaspAP将树莓派变身为无线路由器
  8. 二进制安装mariadb 10.2.16
  9. Python Tricks(七)—— 使用 list 仿真先入先出的队列(FIFOQueue)
  10. session 的工作原理以及使用细节和url编码
  11. 【反向并查集、联通图】P1197 [JSOI2008]星球大战
  12. ES文件浏览器局域网传输文件分析
  13. 魔鬼数学——大数据时代,数学思维的力量
  14. 英特尔边缘软件中心介绍
  15. 应用常驻后台?需要用户对手机做配置
  16. Unity 模拟鼠标点击
  17. Java初学者的建议!
  18. 工程项目成本费用明细表_工程施工合同成本费用明细表有哪些
  19. 办公大师系列经典丛书 诚聘译者
  20. 我,35岁程序员,离职前是这么做的

热门文章

  1. php中什么是伪静态,thinkphp中什么是伪静态?
  2. 计算机通信与网络【笔记自用】
  3. Leetcode 792. 匹配子序列的单词数
  4. 基于MATLAB的数字水印算法研究实现
  5. 【游戏开发实战】使用Unity制作水果消消乐游戏教程(二):随机生成水果
  6. 程序员手工搭建“波音737”模拟驾驶舱,网友直呼牛!
  7. python日期和时间_Python日期和时间
  8. pb代码graph绘图表_程序员轻松绘图神器
  9. Winform中的开关按钮【ToggleButton】
  10. 动态规划(二):矩阵连乘问题