如何计算互联网校验和?

时间:2010-10-21 12:48:10

标签: checksum

我对如何计算互联网校验和有一些疑问。我从书中找不到任何好的解释,所以我在这里问。我不确定这是否是正确的地方,所以如果我在错误的地方询问,我很抱歉。

如果你看下面的例子。 发送以下两条消息:10101001和00111001.校验和以1的补码计算。到目前为止我明白了。但总和如何计算?起初我以为它可能是XOR,但似乎并非如此。

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

然后当他们计算出msg是否正常时。又一次如何计算总和?

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

5 个答案:

答案 0 :(得分:8)

它使用加法,因此名称为“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 |
+------------+-----+----+----+----+---+---+---+---+--------+

答案 1 :(得分:8)

如果通过互联网校验和,你的意思是TCP Checksum有一个很好的探索here甚至一些code

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

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

答案 2 :(得分:2)

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

注意:当添加数字补码算术时,需要将MSB的残留添加到结果中。考虑例如,添加3(0011)和5(0101)。

3' - > 1100 5' - &GT 1010     0110携带1 因此,我们有,0111(1的补码表示-8)。

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

答案 3 :(得分:0)

通过对段中的所有16位字进行求和,在发送端创建UDP校验和,任何溢出被包围,然后执行1的补码,并将结果添加到校验和字段在细分市场内。 在接收方,如果结果是1111 1111 1111 1111,则添加数据包内的所有单词并在其上添加校验和,然后该段有效,否则该段有错误。 〔实施例:   0110 0110 0110 0000   0101 0101 0101 0101

1000 1111 0000 1100

1 0100 1010 1100 0001 //有一个溢出,所以我们把它包起来,意味着将它添加到总和中 总和= 0100 1010 1100 0010 现在让我们来看看1&1的补充 checksum = 1011 0101 0011 1101

在接收器处计算总和,然后将其添加到校验和中   0100 1010 1100 0010

1011 0101 0011 1101

1111 1111 1111 1111 //显然这应该是答案,如果不是则会出现错误 参考文献:计算机网络自上而下的方法[Ross-kurose]

答案 4 :(得分:0)

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

这些是数据包头的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