zoukankan      html  css  js  c++  java
  • IP数据报首部校验和算法

    当用google搜索IP数据报首部校验和算法的时候,总是看到的是代码,没有看到其过程,于是就有了此文,如有错误请指正。文章省略一点,呵呵
     
    IP/ICMP/IGMP/TCP/UDP等协议的校验和算法都是相同的,算法如下:
    在发送数据时,为了计算数IP据报的校验和。应该按如下步骤:
    (1)把IP数据报的首部都置为0,包括校验和字段。
    (2)把首部看成以16位为单位的数字组成,依次进行二进制反码求和。
    (3)把得到的结果存入校验和字段中。
    在接收数据时,计算数据报的校验和相对简单,按如下步骤:
     
    (1)当接收IP包时,需要对报头进行确认,检查IP头是否有误,算法同上2、3步,然后判断取反的结果是否为0,是则正确,否则有错。

      

    1、发送方
      i)将校验和字段置为0,然后将IP包头按16比特分成多个单元,如包头长度不是16比特的倍数,则用0比特填充到16比特的倍数;
     
      ii)对各个单元采用反码加法运算(即高位溢出位会加到低位,通常的补码运算是直接丢掉溢出的高位),将得到的和的反码填入校验和字段;
     
      iii)发送数据包。
     
    2、接收方
      i)将IP包头按16比特分成多个单元,如包头长度不是16比特的倍数,则用0比特填充到16比特的倍数;
     
      ii)对各个单元采用反码加法运算,检查得到的和是否符合是全1(有的实现可能对得到的和会取反码,然后判断最终值是不是全0);
     
    iii) 如果是全1则进行下步处理,否则意味着包已变化从而丢弃之。需要强调的是反码和是采用高位溢出加到低位的,如3比特的反码和运 算:100b+101b=010b(因为100b+101b=1001b,高位溢出1,其应该加到低位,即001b+1b(高位溢出位)=010b)。

     1.实例

    请看我用ominipeek的抓包

    I.将校验和字段置为0,然后将IP包头按16比特分成多个

     

    校验和Header Checksum:0x618D将其重置为0X0000

    将IP包头分段:

            1.  0x4500

            2.  0x0029

            3.  0x44F1

            4.  0x4000

            5.  0x8006

            6.  0x0000 ------->这个为Header Checksum的值,我们前面将其重置为0了

            7.  0xC0A8

            8.  0x01AE

            9.  0x4A7D

    +       10.  0x477D

    -------------------------------------------------------

    将1至10相加求出来的和为:0x29E70

    II.对各个单元采用反码加法运算(即高位溢出位会加到低位,通常的补码运算是直接丢掉溢出的高位),将得到的和的反码填入校验和字段

    0x0002+0x9E70=0x9E72

    0x9E72二进制为:1001 1110 0111 0010

    反码为:0110 0001 1000 1101

    0110 0001 1000 1101的16进制为:0x618D

    看看这个 是否与IP包头中的Checksum相同

    ==========================================================

    当接收到IP对其进行检测

    III.对各个单元采用反码加法运算,检查得到的和是否符合是全1(有的实现可能对得到的和会取反码,然后判断最终值是不是全0)

    当收到IP数据局包的时候,要验证IP头是否正确,则可以这样进行

            1.  0x4500

            2.  0x0029

            3.  0x44F1

            4.  0x4000

            5.  0x8006

            6.  0x618D ------->这个为Header Checksum的值

            7.  0xC0A8

            8.  0x01AE

            9.  0x4A7D

    +       10.  0x477D

    -------------------------------------------------------

    将1至10相加求出来的和为:0x2FFD

    对各个单元采用反码加法运算(即高位溢出位会加到低位,通常的补码运算是直接丢掉溢出的高位),将得到的和的反码填入校验和字段

    0x0002+0x0FFD=0xFFFF

    0xFFFF二进制为:1111 1111 1111 1111

    1111 1111 1111 1111反码为:0

    ====================================================

    关于这一部的补充说明,

    将IP包头分段:
     
            1.  0x4500
     
            2.  0x0029
     
            3.  0x44F1
     
            4.  0x4000
     
            5.  0x8006
     
            6.  0x0000 ------->这个为Header Checksum的值,我们前面将其重置为0了
     
            7.  0xC0A8
     
            8.  0x01AE
     
            9.  0x4A7D
     
    +       10.  0x477D
    ----------------------------------------------------------------------------------------------------------

     
     
     

        

     有些地方需要完善,请参考来源。


    微信公众号: 猿人谷
    如果您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】
    如果您希望与我交流互动,欢迎关注微信公众号
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

  • 相关阅读:
    Visual Studio Code 上java开发环境搭建
    c++编译时打印宏定义
    git使用
    Let's Encrypt申请证书及使用
    使用docker创建aosp编译环境
    项目中使用protobuf 3.0
    ubuntu14.04 安装mono
    ubuntu14.04 安装apache+mysql+php
    Discuz & UCenter 修改手记
    代码细节重构:请对我的代码指手划脚(四)
  • 原文地址:https://www.cnblogs.com/heyonggang/p/2859319.html
Copyright © 2011-2022 走看看