← 返回题目列表

TCP 收到乱序报文会怎么处理?接收端如何重组有序字节流?

中等 第 26 / 30 题 更新于 2026/08/01
TCP乱序重组接收缓冲区

简化版

TCP 接收端按序交付字节流。若收到乱序报文,通常会先放入接收缓冲区,累计 ACK 仍停在缺失字节处;等缺口报文到达后,再把连续区间一起交给应用层。乱序可能由网络多路径、路由变化、重传或调度导致。

详细版

假设接收端期望 Seq=1000

收到 [1000,1199] -> Ack 1200,可交付
收到 [1400,1599] -> Ack 1200,缓存乱序段
收到 [1200,1399] -> Ack 1600,可交付 1200..1599

接收端要处理乱序、重复、重叠报文段,并保证最终交付给应用的是无重复、按顺序的字节流。

完整版教学

一、乱序报文为什么会出现

IP 网络只尽力而为,不保证路径和到达顺序完全稳定。不同报文可能经历不同队列、不同转发路径或不同重传时机。

发送顺序: A, B, C
到达顺序: A, C, B

TCP 必须在端系统里把乱序数据重新整理成有序字节流。

二、接收端的核心状态

接收端最关心的是“下一个期望字节序号”,也就是累计 ACK 的值。

事件接收端动作Ack
收到期望段交付或推进连续区间前进
收到后续乱序段缓存不前进
收到重复段丢弃或合并通常不前进
缺口补齐合并连续区间大幅前进

关键点:乱序数据可以先缓存,但累计确认不能越过缺口。

三、为什么不能直接交付乱序数据

TCP 给应用的是有序字节流。应用层通常没有能力也不应该处理缺洞。

应用读取文件内容
如果中间缺 200 字节,后面先给应用会破坏语义

所以 TCP 层必须等前面的缺失字节到齐。

四、重叠和重复报文怎么处理

重传可能导致接收端再次收到已接收范围的数据,也可能出现部分重叠。

已收 [1000,1499]
又收 [1200,1699]
新增部分只有 [1500,1699]

实现需要按序号范围合并,去掉重复字节,避免交付两次。

五、和快速重传的关系

乱序到达时,接收方会重复确认缺口位置。发送方收到多个重复 ACK 后,可以判断某段可能丢失,触发快速重传。

接收方反复 Ack 1200
发送方推测 1200 开始的数据丢了

如果支持 SACK,接收方还能告诉发送方哪些后续区间已经收到,帮助更精准重传。

六、接收缓冲区的压力

乱序数据占用接收缓冲区。如果缺口长期不补齐,后续数据越积越多,可能导致接收窗口变小,甚至影响发送方继续发送。

乱序缓存多
可用接收缓冲减少
通告窗口变小
发送方被限制

这也是弱网和丢包环境下吞吐下降的原因之一。

七、常见误区与追问

  • 误区:TCP 不会收到乱序包。 IP 层不保证顺序,TCP 负责重组。
  • 误区:乱序包到达后 Ack 会跳到最后。 累计 Ack 不能越过缺口。
  • 误区:重复报文一定是错误。 重传和 ACK 丢失都可能导致重复,TCP 会去重。
  • 追问:乱序数据会丢弃吗? 通常会缓存,受接收缓冲区和实现策略限制。
  • 追问:SACK 有什么帮助? 告知发送方已收到的非连续区间,减少不必要重传。
  • 追问:乱序会影响应用吗? TCP 会屏蔽乱序,应用只看到有序字节流,但可能感到延迟增加。

八、加强记忆

TCP 接收端像拼拼图:先来的后续块可以放旁边,但交给应用必须从缺口前连续交付。累计 ACK 永远指向第一个缺失字节;缺口一补齐,ACK 才能向前跳。