TCP 传输控制协议

本文最后更新于 2025年8月8日 16:19

TCP 协议的特点:面向连接、面向字节流、可靠传输、流量控制、拥塞控制。

面向连接

面向连接 是指在 TCP 通信前,通信双方必须先通过三次握手 建立连接(连接建立阶段),确保通信双方都准备好进行数据传输;在数据传输完后再通过四次挥手 关闭连接(连接释放阶段),确保双方都完成了数据的发送和接收

TCP 连接建立后,通信双方会维护连接的状态信息,包括序列号、窗口大小等,以便进行可靠的数据传输和流量控制。这些状态信息使得 TCP 能够跟踪数据的传输情况,并在必要时进行重传。

面向字节流

应用层TCP 传输层 发送数据时,TCP 并不关心应用层一次发送了多少、什么结构的数据,而是将这些数据当作一串连续的字节流(byte stream) 来看待,然后根据自己的机制进行 分段发送(Segment)。TCP 不保留应用层消息边界,只负责可靠、有序地传输一串字节。

面向字节流传输使得 TCP 协议能够灵活面对多种场景,更好地实现流量控制、拥塞控制和重传等机制,但这同样也会使得消息的边界信息丢失,带来粘包、拆包等问题。

  • 粘包:多条消息被合并在一个 TCP 报文中一次性发送,接收端无法区分消息边界。
  • 拆包:一条完整的消息被拆分到多个 TCP 报文中,分多次到达,接收端读不到完整的消息。

我们可以通过定长消息、消息分隔符、消息头 + 消息体、使用高层协议等方法来解决粘包和拆包的问题。

可靠传输

可靠传输,就是指 数据能够完整、无差错、按顺序地到达接收方。在 TCP 协议中,主要通过以下几点实现可靠传输:

  • 序列号和确认应答
  • 重传
  • 流量控制
  • 拥塞控制

在正常情况下,一般只需要通过序列号和确认应答就可以保证可靠传输:当发送端的数据到达接收主机时,接收端主机会返回一个确认应答,表示已经收到消息。针对数据丢失的问题,则会采用重传机制解决。

超时重传

超时重传是重传的一种方式。发送方在发送数据后,会启动一个定时器。如果在定时器超时前没有收到相应的 ACK,发送方会认为数据丢失,并重新发送这些数据。每次遇到超时重传,超时时间间隔都会设置成前值的二倍。为了解决超时周期较长的问题,又引入了快速重传机制。

快速重传

image.png

快速重传的工作方式是当收到三个相同的 ACK 报文时,会在定时器过期之前,重传丢失的报文段。但快速重传机制依然面临一个问题:重传一个还是重传所有?

举个例子,假设发送方发了 6 个数据,编号的顺序是 Seq1 ~ Seq6 ,但是 Seq2、Seq3 都丢失了,那么接收方在收到 Seq4、Seq5、Seq6 时,都是回复 ACK2 给发送方,但是发送方并不清楚这连续的 ACK2 是接收方收到哪个报文而回复的, 那是选择重传 Seq2 一个报文,还是重传 Seq2 之后已发送的所有报文呢(Seq2、Seq3、 Seq4、Seq5、 Seq6) 呢? 如果只选择重传 Seq2 一个报文,那么重传的效率很低。因为对于丢失的 Seq3 报文,还得在后续收到三个重复的 ACK3 才能触发重传。 如果选择重传 Seq2 之后已发送的所有报文,虽然能同时重传已丢失的 Seq2 和 Seq3 报文,但是 Seq4、Seq5、Seq6 的报文是已经被接收过了,对于重传 Seq4 ~Seq6 折部分数据相当于做了一次无用功,浪费资源。

因此,TCP 协议又引入了 SACK 方法。

SACK 方法

SACK 方法,即 Selevtive Acknowledge 选择性确认。这种方式需要在 TCP 头部「选项」字段里加一个 SACK 的东西,它可以将已收到的数据的信息发送给「发送方」,这样发送方就可以知道哪些数据收到了,哪些数据没收到。知道了这些信息,就可以只重传丢失的数据。

如下图,发送方收到了三次同样的 ACK 确认报文,于是就会触发快速重发机制,通过 SACK 信息发现只有 200~299 这段数据丢失,则重发时,就只选择了这个 TCP 段进行重复。

image.png

流量控制

流量控制(Flow Control)是 TCP 协议为了防止发送方发送过快导致接收方来不及处理而引入的一种机制。TCP 是通过滑动窗口来实现流量控制的。

TCP 头里有一个字段叫 Window,也就是窗口大小。 这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。 所以,通常窗口的大小是由接收方的窗口大小来决定的。 发送方发送的数据大小不能超过接收方的窗口大小,否则接收方就无法正常接收到数据。如果窗口为 0,发送方会暂停发送并周期性发送探测包,直到窗口恢复。

image.png

拥塞控制

TCP 的拥塞控制是为了防止网络中的路由器和链路出现过载而导致的性能下降。和流量控制主要关注接收端不同,它是从网络的承载能力出发进行控制的。TCP 拥塞控制主要依赖四个机制:慢启动(Slow Start)、拥塞避免(Congestion Avoidance)、快速重传(Fast Retransmit)和快速恢复(Fast Recovery)。

  • 慢启动阶段

    初始时,TCP 不知道网络的拥塞程度,为了防止一开始就发送太多数据而导致拥塞,TCP 设置一个拥塞窗口(cwnd),初始值较小(通常为 1 或 10 个 MSS,即 Maximum Segment Size,最大报文段长度)。每收到一个 ACK,就将 cwnd 指数级地增加,快速探索网络的可用带宽。

  • 拥塞避免阶段

    当 cwnd 达到一个阈值(ssthresh,slow start threshold,慢启动门限)后,TCP 进入拥塞避免阶段,将 cwnd 改为线性增长,以避免过快地占满带宽。

  • 快速重传

    如果发送方连续收到三个相同的 ACK(重复 ACK),意味着有一个包丢失了,TCP 会立即重传丢失的数据包,而不等超时,从而提升丢包后的响应速度。

  • 快速恢复

    重传丢包后,不像慢启动那样将 cwnd 重置为 1,而是将其减半并进入拥塞避免阶段,从而提高网络利用率。

拥塞控制

TCP 拥塞控制的核心概念:

  • 拥塞窗口(Congestion Window,cwnd):
    • 发送方维护的窗口,用于控制可以发送但尚未收到确认的数据量。
    • 拥塞窗口的大小根据网络拥塞情况动态调整。
    • 拥塞窗口与接收窗口共同决定了发送方的发送速率。
  • 慢启动阈值(Slow Start Threshold,ssthresh):
    • 用于区分慢启动阶段和拥塞避免阶段的阈值。
    • 当拥塞窗口小于 ssthresh 时,TCP 使用慢启动算法。
    • 当拥塞窗口大于或等于 ssthresh 时,TCP 使用拥塞避免算法。

TCP 拥塞控制的主要算法:

  1. 慢启动(Slow Start):
    • 在连接建立初期或网络拥塞恢复后,TCP 使用慢启动算法。
    • 拥塞窗口初始值为 1 个最大报文段大小(MSS)。
    • 每收到一个 ACK,拥塞窗口大小加倍。
    • 慢启动呈指数增长,直到拥塞窗口达到 ssthresh。
  2. 拥塞避免(Congestion Avoidance):
    • 当拥塞窗口达到 ssthresh 后,TCP 进入拥塞避免阶段。
    • 每收到一个 ACK,拥塞窗口大小增加 1/cwnd。
    • 拥塞避免呈线性增长,避免拥塞窗口增长过快。
  3. 快速重传(Fast Retransmit):
    • 当接收方收到三个重复的 ACK 时,认为发生了丢包。
    • 发送方立即重传丢失的数据包,而无需等待超时。
    • 快速重传可以提高重传效率,减少延迟。
  4. 快速恢复(Fast Recovery):
    • 在快速重传后,TCP 进入快速恢复阶段。
    • 将 ssthresh 设置为当前拥塞窗口的一半。
    • 将拥塞窗口设置为 ssthresh 加上 3 个 MSS。
    • 每收到一个重复的 ACK,拥塞窗口大小加 1。
    • 当收到新的 ACK 时,拥塞窗口大小设置为 ssthresh,并进入拥塞避免阶段。

TCP 拥塞控制的意义:

  • 避免网络拥塞:
    • 通过动态调整发送速率,防止发送过多数据导致网络拥塞。
  • 提高网络利用率:
    • 在网络状况良好时,允许发送方快速增加发送速率,提高网络利用率。
  • 保证网络公平性:
    • 通过拥塞控制算法,确保网络资源的公平分配,避免个别连接占用过多带宽。

TCP 传输控制协议
http://example.com/2025/04/03/TCP 传输控制协议/
作者
Moonike
发布于
2025年4月3日
更新于
2025年8月8日
许可协议