• 课题需要 > 如何计算校验和?


    想要修改一个pcap包,除了对于提取后的每个特征进行修改以外,想要保证数据包的功能,能够重传,还要保证包头的校验和是计算正确的,这就需要按照数据包的具体内容对于包头校验和进行更改。

    那么,都有哪些包头需要计算校验和,校验和又覆盖了哪些内容呢? 首先给出一个总结:

    IP、ICMP、UDP和TCP报文头都有检验和字段,大小都是16bit。

    (1)IP校验和:IP首部。

    (2)ICMP校验和:ICMP首部+ICMP数据;

    (3)UDP、TCP校验和:首部+数据+12个字节伪首部(源IP地址、目的IP地址、协议、TCP/UDP包长)。

    发送数据包的一端会首先根据内容,计算校验和并填充数据包头,这里上述3种校验和的计算方法是基本一致的,包括:

    (1)把校验和字段设置为0。

    (2)把需要校验的数据看成以16位为单位的数字组成,依次进行二进制反码求和。

    (3)把得到的结果存入校验和字段中。

    而上述计算方法对于不同数据包包头的作用范围也不同,区别在于:

    (1)IP校验和:只校验20字节的IP报头。

    (2)ICMP校验和:覆盖整个报文(ICMP报头+ICMP数据)。

    (3)UDP和TCP校验和:不仅覆盖整个报文,而且还有12个字节的IP伪首部,包括源IP地址(4字节)、目的IP地址(4字节)、协议(2字节)、TCP/UDP包长(2字节)。

      另外,需要注意的是,UDP、TCP数据报的长度可以为奇数字节。因为计算时是16位为单位,此时计算校验和时需要在最后增加一个填充字节0(只用于计算校验和,不发送出去)。 而在UDP传输协议中,校验和是可选的,当校验和字段为0时,表明该UDP报文未使用校验和,接收方就不需要校验和检查了。那如果UDP校验和的计算结果是0时怎么办?这里给出答案,如果校验和的计算结果为0,则存入的值为全1(65535),这在二进制反码计算中是等效的。

    接收数据包的一端,则会根据收到的实际内容,与发送端给出的校验和作比较,进行校验,其步骤为:

    (1)把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段;

    (2)检查计算出的校验和的结果是否为0;

    (3)如果等于0,说明被整除,校验和正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。

      

    这里给出二进制反码求和操作的原理:

    (1)二进制反码求和,就是先把两个数取反,然后求和,如果最高位有进位,则向低位进1。

    (2)另外,先取反后相加与先相加后取反,得到的结果是一样的。因此,通常实现代码都是先相加,最后再取反。

    【一个例子】二进制反码求和

      对一个无符号的数,先求其反码,然后从低位到高位,按位相加,有溢出则向高位进1(和一般的二进制法则一样),若最高位有进位,则向最低位进1

      这里的反码和有符号反码不同,不分正负,直接按位取反。此外,进位方式也与我们学习的加法法则不同,最高位有进位,需要向最低位进1。为什么要这样呢?

      对此分析一下,上面的这种操作,使得在发送加法进位溢出时,溢出值并不是10000,而是1111,也就是当相加结果满1111时溢出,这样也可以说明为什么0000和1111都表示0了。

        下面是两种二进制反码求和的运算:

        原码加法运算:3(0011)+5(0101)=8(1000)

                      8(1000)+9(1001)=1(0001)

        反码加法运算:3(1100)+5(1010)=8(0111)

                      8(0111)+9(0110)=2(1101)

        从上面的例子中,当加法未发生溢出时,原码与反码加法运算结果一样;当有溢出时,结果就不一样了,原码是满10000溢出,而反码是满1111溢出,所以相差正好是1。

    此外,还有需要清楚的问题,为什么我们使用的是反码和,而不是直接求和呢?或者是补码和【在计算机里面数据是以补码的形式存在】呢?

    这里给出学习过程中了解到的,在TCP/IP校验和中使用反码求和的一些优点:

    (1)不依赖系统是大端小端。即无论你是发送方计算机或者接收方检查校验和时,都不要调用htons或者ntohs,直接通过算法就可以得到正确的结果。用反码求和时,交换16位数的字节顺序,得到的结果相同,只是字节顺序相应地也交换了;而如果使用原码或者补码求和,得到的结果可能就不同。

    (2)计算和验证校验和比较简单、快速。

    To see I can not see, to know I do not know.
  • 相关阅读:
    VS2010中连接sdf数据库的字符串 Kevin
    找不到请求的 .Net Framework Data Provider。可能没有安装 Kevin
    MVC项目中找不到 DbContext 命名空间 Kevin
    Something About Assert()——C#中的断言 Kevin
    Html.Partial vs Html.RenderPartial & Html.Action vs Html.RenderAction Kevin
    .NET 中的双问号 Kevin
    苹果公司一道面试题 Kevin
    The diffrence between TempData and ViewBag and ViewData Kevin
    GRUB整体分析
    忠诚的成本看房产大鳄冯仑如何处理看待忠诚
  • 原文地址:https://www.cnblogs.com/aluomengmengda/p/15649665.html
Copyright © 2020-2023  润新知