Skip to content

TCP:连接、可靠性、流量控制与拥塞控制

TCP 是 Transmission Control Protocol,中文常叫“传输控制协议”。

如果压缩成一句话,它主要解决的是 在不可靠的网络环境里,如何为应用提供面向连接、可靠、按序的字节流传输。


1. TCP 到底在解决什么问题

网络本身会遇到很多现实问题:

  1. 数据包可能丢
  2. 包可能乱序
  3. 包可能重复
  4. 接收方处理速度可能跟不上
  5. 网络本身可能已经拥塞

TCP 出现,就是为了在这些现实条件下,把传输过程尽量组织得更稳定。

它主要负责:

  1. 建立连接
  2. 可靠传输
  3. 按序交付
  4. 流量控制
  5. 拥塞控制

2. 为什么说 TCP 是“面向连接”

面向连接 不是说网线真的被你独占了一根。

更贴近这个概念的说法是:

  1. 双方在正式传数据前,要先建立一段逻辑连接状态
  2. 后续传输过程里,双方都要维护这段连接的状态
  3. 传完后还要有连接释放过程

所以 TCP 的“连接”更像 一段被双方共同维护的通信状态,而不是物理线路。


3. 三次握手在做什么

三次握手不是为了仪式感,而是为了确认两件事:

  1. 我能发给你
  2. 你也能发给我

最简化地理解:

  1. 客户端发 SYN
  2. 服务端回 SYN + ACK
  3. 客户端再回 ACK

这样双方就能确认:

  1. 双向收发能力基本可用
  2. 初始序列号协商完成
  3. 后续可以进入可靠传输阶段

4. 从发起请求到收到响应,TCP 这一层具体在做什么

如果只记“三次握手”,还是不够理解 TCP 在真实请求里扮演的角色。

更完整的过程通常是:

  1. 客户端先和服务端建立连接
  2. 连接建立后,客户端把应用层数据写入发送缓冲区
  3. TCP 把这段字节流切成合适的报文段
  4. 每个报文段带上序列号后发出去
  5. 服务端收到后,会根据序列号确认、重排并交给上层应用
  6. 应用处理后,服务端再把响应数据通过同一连接发回客户端
  7. 客户端继续确认收到的数据,直到本轮请求响应完成
  8. 如果连接不再使用,再进入连接关闭过程

这里最值得记的不是报文格式细节,而是:

TCP 既负责建立连接状态,也负责在连接存在期间持续管理发送、确认、重传、排序和关闭。`


5. 一张 TCP 请求响应过程图

mermaid
sequenceDiagram
    participant Client as 客户端
    participant Server as 服务端

    Client->>Server: SYN
    Server-->>Client: SYN + ACK
    Client->>Server: ACK
    Note over Client,Server: TCP 连接建立

    Client->>Server: 发送请求数据段 seq=100
    Server-->>Client: ACK=...
    Client->>Server: 发送后续数据段
    Server->>Server: 按序重组并交给应用

    Server-->>Client: 返回响应数据段
    Client->>Client: 按序重组并交给应用
    Client-->>Server: ACK=...

    Client->>Server: FIN
    Server-->>Client: ACK
    Server-->>Client: FIN
    Client->>Server: ACK
    Note over Client,Server: TCP 连接关闭

这张图的重点不是让你背每个序列号,而是先理解:

  1. 请求和响应都跑在同一条连接上
  2. 传输过程不是“一发就完”,而是伴随确认和可能的重传
  3. 连接的建立和关闭本身也是协议过程的一部分

6. TCP 为什么能保证可靠和按序

它不是靠“网络突然变可靠”,而是靠自己补机制。

这些机制通常包括:

  1. 序列号
  2. 确认应答 ACK
  3. 超时重传
  4. 乱序重排
  5. 去重

也就是说,TCP 的可靠性来自 协议机制 + 连接状态维护,而不是物理网络天生可靠。


7. 流量控制和拥塞控制不是一回事

这是 TCP 里特别容易混的一组概念。

5.1 流量控制

流量控制更关心:

接收方来不来得及处理。

如果发送方太快,接收方缓冲区可能吃不消。

所以流量控制本质上是端到端双方之间的速度协调。

5.2 拥塞控制

拥塞控制更关心:

整个网络现在是不是已经太堵了。

它不是只看接收方,而是看网络链路整体承受能力。

所以:

  1. 流量控制解决“接收端吃不吃得下”
  2. 拥塞控制解决“网络扛不扛得住”

🌟 这两个词经常一起出现,但解决的问题并不相同。


8. TCP 的能力边界

这部分很重要,因为很多误解都来自把 TCP 想得过大。

6.1 TCP 负责端到端可靠传输

它负责:

  1. 建连接
  2. 维护连接状态
  3. 让字节流尽量可靠、按序送达

6.2 TCP 不负责机器级路由

它依赖下层 IP 去把包送到目标主机。

6.3 TCP 不理解应用语义

TCP 来说,网页请求、RPC 调用、聊天消息,本质上都只是字节流。

6.4 TCP 不是“永不丢失”

更贴近实际情况的说法是,它会通过重传和控制机制尽量把数据交付给应用,但在超时、异常断连、对端不可达等情况下,连接仍然会失败。


9. 为什么一个 HTTP 请求在 TCP 里看起来像“字节流”

这部分非常关键。

TCP 来说,它看到的不是:

  1. 这是一个 GET
  2. 这是一个 JSON
  3. 这是一个状态码

它看到的只是连续字节。

例如浏览器发出:

http
GET /api/users/1001 HTTP/1.1
Host: example.com

到了 TCP 这一层,更像是:

  1. 一串待发送字节
  2. 被切分成多个报文段
  3. 再由对端按序重组成原始字节流

所以很多应用层协议都会强调:

  1. 报文边界怎么定义
  2. 长度如何表示
  3. 粘包拆包怎么处理

因为 TCP 提供的是字节流,不替你保留应用层消息边界。


10. 一个最小的连接示意

可以用 curl 观察一个最普通的 TCP 应用场景:

bash
curl -v https://example.com

你会看到请求里有:

  1. 建立连接
  2. 发送请求
  3. 接收响应
  4. 连接复用或关闭

如果进一步抓包,会更容易看到三次握手、数据传输和四次挥手这些过程。


11. 为什么很多业务系统默认偏爱 TCP

因为大部分业务系统更关心:

  1. 数据不要乱
  2. 请求不要莫名丢
  3. 结果要可预期

例如:

  1. HTTP/1.1
  2. 数据库连接
  3. RPC
  4. 消息中间件客户端连接

这些场景通常都更偏可靠传输,而不是“少一点协议开销就行”。


12. 常见误区

12.1 以为 TCP 更慢,所以不适合所有高性能场景

不准确。

大量高性能系统依然运行在 TCP 之上,关键要看业务到底要可靠性还是更低时延。

12.2 以为有 TCP 就不需要应用层重试和超时

不是。

TCP 解决的是传输层可靠性,不是业务层成功语义。

12.3 以为三次握手只是背诵题

真正重要的是理解它为什么要确认双向收发能力和连接状态。


13. 一句话总结

TCP 这条主线,本质上是在解决 如何在不可靠网络上,为应用提供面向连接、可靠、按序、可控制速率的字节流传输。

基于 VitePress 构建的个人技术笔记。