如何计算 TCP 报文中的确认号码 (ack number)?
ACK number 是接收方期望收到的下一个字节序列号,ACK 的计算方式基于已接收数据包的最后一个有序字节。
确认号码 (ack number) 是接收方期望收到的下一个字节的序列号,计算公式为:
ack number = 接收到的最后一个有序字节的序列号 + 该数据的长度 + 1
分解说明:
- 序列号 (SEQ) 基础
TCP 为每个字节分配唯一的序列号,发送方在报文头部指定初始序列号和携带的数据长度。- 若发送数据的首个字节序列号为
x
,数据长度为len
,则数据覆盖范围:x
至x + len - 1
。
- 若发送数据的首个字节序列号为
- 确认号 (ACK) 计算逻辑
- 接收方计算规则:
ack number = 已收到的连续数据的最后一个字节序号 + 1
例如:- 收到数据 SEQ=100,长度150 → 字节范围 100-249,此时 ACK=250。
- 若收到乱序数据(SEQ=300),但 SEQ=250 的数据缺失 → ACK 仍为250(等待缺失数据),不立即确认乱序部分。
- 接收方计算规则:
- 传输过程示例
// 发送方行为: 发送报文1: SEQ=100, 数据长度=150 → 数据字节100-249 发送报文2: SEQ=250, 数据长度=100 → 数据字节250-349 // 接收方行为: 成功接收报文1 → 返回ACK=250(因250是下一个预期字节序号) 成功接收报文2 → 返回ACK=350
- 特殊场景:三次握手
建立连接时:- 客户端首次 SYN: SEQ=X
- 服务端回复 SYN-ACK:
ACK=X+1 (确认客户端SYN, 因SYN占用一序号)
SEQ=Y (服务端自身初始序列号)
- 优化机制:延迟确认 (Delayed ACK)
接收方可能将 ACK 与其他数据合并发送,避免每次接收都单独响应:示例: 客户端发送: SEQ=500, 长度=200 → 数据500-699 服务端需回复数据 → 返回报文: ACK=700, SEQ=服务端序列号 (代替单独ACK包)
要点总结
ACK 本质是 期望下次收到的起始字节序号,核心公式:ACK = 最高连续字节序号 + 1。通过该机制协同 SEQ 实现可靠传输。