【问题标题】:How to calculate Internet checksum?如何计算互联网校验和?
【发布时间】:2011-04-28 14:33:03
【问题描述】:

我有一个关于如何计算 Internet 校验和的问题。我从书上找不到任何好的解释,所以我在这里问。

看看下面的例子。

发送以下两条消息:10101001 和 00111001。校验和是用 1 的补码计算的。到目前为止我明白了。但是总和是怎么计算的呢?一开始我以为可能是异或,但好像不是这样的。

              10101001
              00111001
              --------
   Sum        11100010
   Checksum:  00011101

然后当他们计算消息是否正常到达时。又是如何计算总和的?

               10101001
               00111001
               00011101
               --------
   Sum         11111111
   Complement  00000000  means that the pattern is O.K.

【问题讨论】:

    标签: checksum


    【解决方案1】:

    这是一个完整的示例,其中包含 IPv4 数据包的真实标头。

    在以下示例中,我使用bcprintfhere strings 来计算标头校验和并进行验证。因此,通过复制粘贴命令在 Linux 上重现结果应该很容易。

    这些是我们示例数据包头的 20 个字节:

    45 00 00 34 5F 7C 40 00 40 06 [00 00] C0 A8 B2 14 C6 FC CE 19
    

    发件人尚未计算校验和。方括号中的两个字节是校验和的位置。校验和的值最初设置为零。

    我们可以在心理上将此标头拆分为 10 个 16 位值的序列:0x4500、0x0034、0x5F7C 等。

    让我们看看数据包的发送者是如何计算包头校验和的:

    1. 将所有 16 位值相加得到 0x42C87:bc <<< 'obase=16;ibase=16;4500 + 0034 + 5F7C + 4000 + 4006 + 0000 + C0A8 + B214 + C6FC + CE19'
    2. 前导数字 4 是进位计数,我们将其与其余数字相加得到 0x2C8B:bc <<< 'obase=16;ibase=16;2C87 + 4'
    3. 取反¹ 0x2C8B 得到校验和:0xD374

    最后,将校验和插入到头部:

    45 00 00 34 5F 7C 40 00 40 06 [D3 74] C0 A8 B2 14 C6 FC CE 19
    

    现在可以发送标头了。

    IPv4 数据包的接收者然后以相同的方式创建接收到的标头的校验和:

    1. 将所有 16 位值相加得到 0x4FFFB:bc <<< 'obase=16;ibase=16;4500 + 0034 + 5F7C + 4000 + 4006 + D374 + C0A8 + B214 + C6FC + CE19'
    2. 再次,有一个进位计数,所以我们将其添加到其余部分以获得 0xFFFF:bc <<< 'obase=16;ibase=16;FFFB + 4'
    3. 如果校验和为 0xFFFF,在我们的例子中,IPv4 标头是完整的。

    请参阅Wikipedia entry 了解更多信息。


    ¹反转十六进制数意味着将其转换为二进制,翻转位,然后再次将其转换为十六进制。您可以这样做 online 或使用 Bash:hex_nr=0x2C8B; hex_len=$(( ${#hex_nr} - 2 )); inverted=$(printf '%X' "$(( ~ hex_nr ))"); trunc_inverted=${inverted: -hex_len}; echo $trunc_inverted

    【讨论】:

      【解决方案2】:

      UDP 校验和是在发送端通过对段中的所有 16 位字求和来创建的,任何溢出都会被环绕,然后执行 1 的补码,并将结果添加到段内的校验和字段中。 在接收方,添加数据包内的所有字,如果结果为 1111 1111 1111 1111,则在其上添加校验和,则该段有效,否则该段有错误。 示例:

        0110 0110 0110 0000
        0101 0101 0101 0101
        1000 1111 0000 1100
      --------------------
      1 0100 1010 1100 0001 //there is an overflow so we wrap it up, means add it to the sum
      the sum = 0100 1010 1100 0010
      

      现在让我们取 1 的补码

      checksum = 1011 0101 0011 1101
      

      在接收端计算总和,然后添加到校验和

        0100 1010 1100 0010
        1011 0101 0011 1101
      ----------------------
        1111 1111 1111 1111 //clearly this should be the answer, if it isn't then there is an error
      

      references:计算机网络自上而下的方法[Ross-kurose]

      【讨论】:

        【解决方案3】:

        它使用加法,因此得名“sum”。 10101001 + 00111001 = 11100010。

        例如:

        +------------+-----+----+----+----+---+---+---+---+--------+
        | bin value  | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | result |
        +------------+-----+----+----+----+---+---+---+---+--------+
        | value 1    |   1 |  0 |  1 |  0 | 1 | 0 | 0 | 1 |    169 |
        | value 2    |   0 |  0 |  1 |  1 | 1 | 0 | 0 | 1 |     57 |
        | sum/result |   1 |  1 |  1 |  0 | 0 | 0 | 1 | 0 |    226 |
        +------------+-----+----+----+----+---+---+---+---+--------+
        

        【讨论】:

        • 进位如何处理?进位是否被丢弃?
        • @Ayos:取决于数字的大小。理论上,1 + 1 = 10,额外的只是继续向左移动。在真正的硬件上,通常会在 8、16、32 或 64 位发生溢出,新数字的含义取决于您使用的是有符号整数以及您处理的是 1s 补码还是 2s 补码系统
        【解决方案4】:

        互联网校验和的计算使用补码算法。考虑校验和的数据是一个 8 位整数序列。首先,您需要使用补码算法将它们相加,然后取结果的补码。

        注意:在将数字相加时,需要将 MSB 的结转添加到结果中。例如,考虑添加 3(0011) 和 5(0101)。

        3'->1100 5'->1010 0110 进位为 1 这样我们就有了 0111(1 的 -8 的补码表示)。

        校验和是上一步获得的结果的 1 的补码。因此我们有 1000。如果不存在进位,我们只需对求和阶段获得的结果进行补充。

        【讨论】:

          【解决方案5】:

          如果您所说的互联网校验和是指 TCP 校验和,则有一个很好的解释 here 甚至一些 code

          当您计算校验和时,请记住,它不仅是数据的函数,而且是“伪标头”的函数,它将源 IP、目标 IP、协议和 TCP 数据包的长度放入数据中校验和。这将 tcp 元数据与 IP 标头中的某些数据联系起来。

          TCP/IP Illustrated Vol 1 是一个很好的参考,并详细解释了它。

          【讨论】:

          • netfor2.com 的链接已失效。
          猜你喜欢
          • 1970-01-01
          • 2011-05-06
          • 1970-01-01
          • 2011-02-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-01
          • 2015-12-21
          相关资源
          最近更新 更多