TCP可靠传输
TCP 保证数据不丢、不乱序,靠的是三个机制:序号确认、超时重传、滑动窗口。
序号与确认
TCP 把数据看成一串连续的字节,每个字节都有编号。发送方发出一段数据,接收方回一个 ACK 告诉发送方”这个序号之前的我都收到了”。
没收到 ACK,发送方就重传。
滑动窗口
一包一包等 ACK 太慢,滑动窗口允许发送方连续发多包,不用等每一包的 ACK。
窗口大小由接收方决定——接收方在 ACK 里告诉发送方自己的缓冲区还剩多少,发送方不能超过这个量。这也是流量控制的基础,详见 TCP流量与拥塞控制。
TCP 的滑动窗口和数据链路层的滑动窗口原理相同,区别在于:
- TCP 按字节确认,不是按帧
- TCP 窗口大小动态变化,受流量控制和拥塞控制双重约束
超时重传
发送方发出数据后启动计时器,超时还没收到 ACK 就重传。
计时器时间(RTO)不是固定的,TCP 会根据网络往返时间(RTT)动态调整,网络慢就等久一点。
快重传
超时重传要等计时器到期,反应慢。快重传是一个优化:
接收方收到乱序的包时,每次都重复发同一个 ACK(催促发送方补那个缺的包)。发送方连续收到 3 个重复 ACK,不等超时,立刻重传那个包。
粘包问题
TCP 是字节流,也就是一段一段的数据连续写入缓冲区,没有天然的边界。发送方发了两条消息,接收方可能一次收到一条半,也可能两条拼在一起收到。
UDP 不会有这个问题,因为 UDP 面向报文,一发一收天然有边界。
解决方法由应用层处理,常见三种:
- 固定长度:每条消息固定 N 字节,不够补齐
- 分隔符:消息之间加特殊字符(如
\n),接收方按分隔符切割 - 长度前缀:消息头部写明数据长度,接收方先读长度再读数据
如果你正在跟随梳理, 返回 TCP←