Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

序号与确认

复习

  • 三次握手:双方同步各自的初始序号与收发能力
  • TCP 为什么需要连接:可靠传输需要双方维护状态
  • UDP:不保证送达与顺序

TL;DR

  • TCP 给每个字节编号,接收方按序号判断丢失、重复与乱序
  • 接收方用确认告诉发送方“我已经收到了哪里”
  • 累积确认:确认到某个序号,表示它之前的都收到了
  • 序号与确认,是重传和顺序控制的基础

正文

  连接建立后,双方约定好了初始序号。现在可以正式传数据了。可数据在不可靠的网络里会丢失、重复、乱序,接收方怎么知道“我拿到的是不是完整的、正确的”?

  答案是把字节都编上号,再让接收方逐段确认。

给每个字节编号

  TCP 把数据看作一条字节流,并为每个字节编上序号。发送方发出一段数据时,会带上“这一段从第几个字节开始”。

  接收方拿到后,就能据此判断:

  • 序号正好是期望的:收下,继续往后
  • 序号重复了:说明是之前那段的副本,直接丢弃
  • 序号跳过了:说明中间丢了,先记下缺口

  有了序号,接收方就不再是“闷头收”,而是能清楚地知道“我收到哪了、还缺哪段”。

确认:告诉对方我的进度

  光自己知道还不够,发送方也得知道。于是接收方会回确认(ACK),告诉发送方自己收到了哪里。

  TCP 用的是累积确认:确认里填的,通常是“我下一个期望的序号”。这句话的含义是——这个序号之前的字节,我都已经收到了。

  比如接收方回“下一个期望是 1001”,就等于说“0 到 1000 这段我都拿到了”。发送方一看便知:这部分可以放心,不用再重发了。

为什么确认“下一个期望的”

  你可能会想:为什么不直接说“我最后收到的是 1000”?

  因为“下一个期望的序号”更精确,也更不易混淆。它明确划出一条分界线:分界线左侧,全都收妥了;分界线右侧,还没到。 如果只说“最后收到 1000”,一旦有乱序、有缺口,就容易含糊。用“下一个期望”,发送方一眼就能看出“该从哪里接着发、哪里需要补”。

思考题 1

  为什么确认“下一个期望的序号”,比确认“最后收到的序号”更清晰?

思考题 2

  接收方收到一个重复的段,为什么可以直接丢弃?

小结

知识点

  • TCP 为字节流编号,用于判断丢失、重复与乱序
  • 接收方用确认告知收到进度
  • 累积确认表示“该序号之前都已收到”
  • 序号与确认是可靠传输的基础

参考资料

  1. Wikipedia(zh):传输控制协议:序号、确认与可靠传输
  2. Wikipedia(zh):GO-BACK-N:基于确认与重传的传输机制

思考题答案(仅供参考)

思考题 1

  “下一个期望的序号”直接划出了一条清晰的界线:它之前的都收妥了,它之后的还没到。这样发送方一眼就能知道从哪儿接着发、哪里需要补。而“最后收到的序号”在有乱序和缺口时含义模糊,容易让人误解进度。

思考题 2

  因为它携带的字节序号小于接收方当前的期望值,说明这段数据之前已经收到并确认过了。重复处理毫无意义,丢弃即可,同时通常还会再回一个确认,提醒对方进度。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪