Appearance
题目
若 UDP 协议在计算校验和过程中,计算机得到中间结果为 1011 1001 1011 0110 时,还需要加上最后一个 16 位数 0110 0101 1100 0101,则最终计算得到的校验和是( )
错因
A
漏了最后两步里的"溢出位回卷加回"——直接用普通二进制加法 ,丢掉最高位的进位 1,得到 。错的根源:把"反码(1's complement)求和"当成普通的二进制求和,没有把溢出的 carry 加回低位。而且最后一步没取反——这是 A 双重出错。
B
加法计算正确(含 carry 回卷得到 ),但忘了最后一步取反——UDP 校验和的算法是"反码求和后再取反",B 卡在反码求和的中间结果上没继续走完。常见的"差一步陷阱"。
D
加法和取反都做了,但加法忘了 carry 回卷——直接对 (A 选项的中间结果)取反得到 。即 D = NOT(A),所以 D 与 A 是同一类错(漏 carry 回卷),区别仅在 D 多走了取反。
总解析
第一步:明确 UDP 校验和的算法
UDP / TCP / IP 校验和都用 16 位反码求和(1's complement sum)+ 取反 的算法:
- 把所有 16 位字段按二进制相加
- 若最高位有进位(carry),把这个 1 回加到结果最低位(这就是"反码求和"的关键步骤)
- 把最终的求和结果按位取反,得到校验和
第二步:执行二进制加法
1011 1001 1011 0110 (中间结果)
+ 0110 0101 1100 0101 (最后一个 16 位数)
= ?按位相加(从右到左,记录进位):
| 位 | A | B | 进位 in | 和 | 进位 out |
|---|---|---|---|---|---|
| 0 | 0 | 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 0 | 1 | 0 |
| 2 | 1 | 1 | 0 | 0 | 1 |
| 3 | 0 | 0 | 1 | 1 | 0 |
| 4 | 1 | 0 | 0 | 1 | 0 |
| 5 | 1 | 0 | 0 | 1 | 0 |
| 6 | 0 | 1 | 0 | 1 | 0 |
| 7 | 1 | 1 | 0 | 0 | 1 |
| 8 | 1 | 1 | 1 | 1 | 1 |
| 9 | 1 | 0 | 1 | 0 | 1 |
| 10 | 0 | 1 | 1 | 0 | 1 |
| 11 | 1 | 1 | 1 | 1 | 1 |
| 12 | 1 | 0 | 1 | 0 | 1 |
| 13 | 0 | 1 | 1 | 0 | 1 |
| 14 | 1 | 1 | 1 | 1 | 1 |
| 15 | 1 | 0 | 1 | 0 | 1 |
得到 17 位结果:。
第三步:carry 回卷
把溢出的最高位 1 加回低位:
0001 1111 0111 1011
+ 1
= 0001 1111 0111 1100反码求和最终结果 = (这就是选项 B 给的中间值)。
第四步:按位取反得到校验和
NOT( 0001 1111 0111 1100 )
= 1110 0000 1000 0011最终校验和 = 。
最终答案是 C。
用十六进制快速验算:
- (17 位)
- carry 回卷:
- 取反: ✓
编者注(生僻术语):「反码求和」(1's complement sum)与「补码求和」(2's complement sum)是两套不同算法:① 反码求和把溢出 carry 加回低位("end-around carry"),适合用于校验和这种"和等于零或 -0 等价"的场景;② 补码求和直接丢弃溢出位,适合普通整数加减。UDP/TCP/IP 校验和统一用反码求和,是历史习惯(与早期机器架构相关),不要和编程里常用的补码加法混了。