Appearance
题目
主机甲与主机乙之间已建立一个 TCP 连接,双方持续有数据传输,且数据无差错与丢失。若甲收到 1 个来自乙的 TCP 段,该段的序号为 1913、确认序号为 2046、有效载荷为 100 字节,则甲立即发送给乙的 TCP 段的序号和确认序号分别是( )。
错因
A
序号 2046 对(甲新发段的 seq = 乙告知的 ack = 甲下一个该发的字节序号);但确认序号 2012 错——应该是 1913 + 100 = 2013。错的根源:少加 1,可能算成"1913 + 99 = 2012"(漏算端点)。
C
序号 2047 错——把"乙的 ack = 2046(即甲下一个该发的字节)"误以为还要 +1。这里不需要 +1:ack 字段已经表示"我下一个期待的序号",所以甲下一个发的字节序号直接 = 2046。错的根源:把 SYN/FIN 的 +1 规则错套到普通数据段。
D
同 C,序号 2047 错(多 +1);确认序号 2013 对。错的根源:对甲的 seq 多加了 1。
总解析
第一步:理清 TCP 双向序号
TCP 是全双工——甲和乙各维护独立的发送字节流序号:
| 流向 | 谁发 | 用谁的序号 |
|---|---|---|
| 甲 → 乙 | 甲 | 甲的发送序号 |
| 乙 → 甲 | 乙 | 乙的发送序号 |
每端发送方在 TCP 头里:
- seq:本段第一字节在自己流中的序号
- ack:对对方流已收到字节的累计确认("我下一个期待的字节")
第二步:分析乙发的段
乙发给甲的段携带:
| 字段 | 值 | 含义 |
|---|---|---|
| seq = 1913 | 乙这段的第一字节在乙的流中是 1913 | |
| ack = 2046 | 乙告诉甲:"我已收到甲流的字节 2045 及之前,我下一个期待 2046" | |
| 有效载荷 100 B | 乙这段携带 100 字节数据,覆盖乙流的 1913 ~ 2012 |
第三步:甲准备回复时的两个字段
甲的 seq(甲下一个该发的字节序号):
由乙的 ack 决定 = 2046——乙说"我下一个期待 2046",甲就从 2046 开始发。
甲的 ack(甲对乙的累计确认):
甲已收完乙流的 1913 ~ 2012(乙发了 100 字节),下一个期待的乙字节 = $2012 + 1 = $ 2013。
或更直观:
第四步:核对
甲发出的段:seq = 2046、ack = 2013 → B。
最终答案是 B(2046、2013)。
编者注(生僻术语):TCP 的 ack 字段表示"我下一个期待的字节序号",含义是"我已经累计收到 ack-1 这个字节及之前的所有字节"。用一句话记:
也即"我说我期待哪一字节,对方就从那字节开始发"。这条规则贯穿三次握手、数据传输、四次挥手所有 TCP 交互。本题甲对乙的 ack 计算就是这条规则的直接应用。