IP,TCP,UDP Checksum校验
IP数据报的校验:
IP数据报只需要对数据头进行校验,步骤如下:
- 将接收到的数据的checksum字段设置为0
- 把需要校验的字段的所有位划分为16位(2字节)的字
- 把所有16位的字相加,如果遇到进位,则将高于16字节的进位部分的值加到最低位上,举例,0xBB5E+0xFCED=0x1 B84B,则将1放到最低位,得到结果是0xB84C
- 将所有字相加得到的结果应该为一个16位的数,将该数取反则可以得到检验和checksum。
上述第2步中也可以不用每次把进位加到低位,可以等所有数据计算结束再将高位16个字依次加到低位,直到最后结果是两个字节为止,例如所有数据相加后为0xb6e51c2a3,首先将其低位2个字节和剩余的高位字节相加0xB6E51+0xC2A3=0xC30F4,对得到的再次将低2个字节和剩余的高位相加:0x30F4+0XC=0X3100
TCP/UDP数据报的校验
一、下面的图是一个UDP的检验和所需要用到的所有信息,包括三个部分:
- UDP伪首部
- UDP首部
- UDP的数据部分
首先解释下伪首部的概念,伪首部的数据都是从IP数据报头获取的。其目的是让UDP两次检查数据是否已经正确到达目的地,只是单纯为了做校验用的。
还有一个概念十分重要,那就是16位UDP总长度,该长度是UDP头和数据的总长度。剩下的校验算法和IP数据报的校验方法一致了。
例子
举个例子来解释该校验方法:
- 首先将检验和部分添零;
- 然后将TCP伪首部部分,TCP首部部分,数据部分都划分成16位的一个个16进制数
- 将这些数逐个相加,记得溢出的部分加到最低位上,这是循环加法:
0xc0a8+ 0x0166+……+0x0402=0x9b49 - 最后将得到的结果取反,则可以得到检验和位0x64B6
下面一段代码里的ChecksumTcpUdp()和ChecksumIp()可以用来检验以上步骤。各位程序员请自行用tcpdump截一段数据来检验一下。
https://github.com/CasperWu/Projects/tree/master/C%2B%2B/utility/src