Appearance
TCP:连接、可靠性、流量控制与拥塞控制
TCP 是 Transmission Control Protocol,中文常叫“传输控制协议”。
如果压缩成一句话,它主要解决的是 在不可靠的网络环境里,如何为应用提供面向连接、可靠、按序的字节流传输。
1. TCP 到底在解决什么问题
网络本身会遇到很多现实问题:
- 数据包可能丢
- 包可能乱序
- 包可能重复
- 接收方处理速度可能跟不上
- 网络本身可能已经拥塞
TCP 出现,就是为了在这些现实条件下,把传输过程尽量组织得更稳定。
它主要负责:
- 建立连接
- 可靠传输
- 按序交付
- 流量控制
- 拥塞控制
2. 为什么说 TCP 是“面向连接”
面向连接 不是说网线真的被你独占了一根。
更贴近这个概念的说法是:
- 双方在正式传数据前,要先建立一段逻辑连接状态
- 后续传输过程里,双方都要维护这段连接的状态
- 传完后还要有连接释放过程
所以 TCP 的“连接”更像 一段被双方共同维护的通信状态,而不是物理线路。
3. 三次握手在做什么
三次握手不是为了仪式感,而是为了确认两件事:
- 我能发给你
- 你也能发给我
最简化地理解:
- 客户端发
SYN - 服务端回
SYN + ACK - 客户端再回
ACK
这样双方就能确认:
- 双向收发能力基本可用
- 初始序列号协商完成
- 后续可以进入可靠传输阶段
4. 从发起请求到收到响应,TCP 这一层具体在做什么
如果只记“三次握手”,还是不够理解 TCP 在真实请求里扮演的角色。
更完整的过程通常是:
- 客户端先和服务端建立连接
- 连接建立后,客户端把应用层数据写入发送缓冲区
TCP把这段字节流切成合适的报文段- 每个报文段带上序列号后发出去
- 服务端收到后,会根据序列号确认、重排并交给上层应用
- 应用处理后,服务端再把响应数据通过同一连接发回客户端
- 客户端继续确认收到的数据,直到本轮请求响应完成
- 如果连接不再使用,再进入连接关闭过程
这里最值得记的不是报文格式细节,而是:
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 连接关闭这张图的重点不是让你背每个序列号,而是先理解:
- 请求和响应都跑在同一条连接上
- 传输过程不是“一发就完”,而是伴随确认和可能的重传
- 连接的建立和关闭本身也是协议过程的一部分
6. TCP 为什么能保证可靠和按序
它不是靠“网络突然变可靠”,而是靠自己补机制。
这些机制通常包括:
- 序列号
- 确认应答
ACK - 超时重传
- 乱序重排
- 去重
也就是说,TCP 的可靠性来自 协议机制 + 连接状态维护,而不是物理网络天生可靠。
7. 流量控制和拥塞控制不是一回事
这是 TCP 里特别容易混的一组概念。
5.1 流量控制
流量控制更关心:
接收方来不来得及处理。
如果发送方太快,接收方缓冲区可能吃不消。
所以流量控制本质上是端到端双方之间的速度协调。
5.2 拥塞控制
拥塞控制更关心:
整个网络现在是不是已经太堵了。
它不是只看接收方,而是看网络链路整体承受能力。
所以:
- 流量控制解决“接收端吃不吃得下”
- 拥塞控制解决“网络扛不扛得住”
🌟 这两个词经常一起出现,但解决的问题并不相同。
8. TCP 的能力边界
这部分很重要,因为很多误解都来自把 TCP 想得过大。
6.1 TCP 负责端到端可靠传输
它负责:
- 建连接
- 维护连接状态
- 让字节流尽量可靠、按序送达
6.2 TCP 不负责机器级路由
它依赖下层 IP 去把包送到目标主机。
6.3 TCP 不理解应用语义
对 TCP 来说,网页请求、RPC 调用、聊天消息,本质上都只是字节流。
6.4 TCP 不是“永不丢失”
更贴近实际情况的说法是,它会通过重传和控制机制尽量把数据交付给应用,但在超时、异常断连、对端不可达等情况下,连接仍然会失败。
9. 为什么一个 HTTP 请求在 TCP 里看起来像“字节流”
这部分非常关键。
对 TCP 来说,它看到的不是:
- 这是一个
GET - 这是一个 JSON
- 这是一个状态码
它看到的只是连续字节。
例如浏览器发出:
http
GET /api/users/1001 HTTP/1.1
Host: example.com到了 TCP 这一层,更像是:
- 一串待发送字节
- 被切分成多个报文段
- 再由对端按序重组成原始字节流
所以很多应用层协议都会强调:
- 报文边界怎么定义
- 长度如何表示
- 粘包拆包怎么处理
因为 TCP 提供的是字节流,不替你保留应用层消息边界。
10. 一个最小的连接示意
可以用 curl 观察一个最普通的 TCP 应用场景:
bash
curl -v https://example.com你会看到请求里有:
- 建立连接
- 发送请求
- 接收响应
- 连接复用或关闭
如果进一步抓包,会更容易看到三次握手、数据传输和四次挥手这些过程。
11. 为什么很多业务系统默认偏爱 TCP
因为大部分业务系统更关心:
- 数据不要乱
- 请求不要莫名丢
- 结果要可预期
例如:
HTTP/1.1- 数据库连接
RPC- 消息中间件客户端连接
这些场景通常都更偏可靠传输,而不是“少一点协议开销就行”。
12. 常见误区
12.1 以为 TCP 更慢,所以不适合所有高性能场景
不准确。
大量高性能系统依然运行在 TCP 之上,关键要看业务到底要可靠性还是更低时延。
12.2 以为有 TCP 就不需要应用层重试和超时
不是。
TCP 解决的是传输层可靠性,不是业务层成功语义。
12.3 以为三次握手只是背诵题
真正重要的是理解它为什么要确认双向收发能力和连接状态。
13. 一句话总结
TCP 这条主线,本质上是在解决 如何在不可靠网络上,为应用提供面向连接、可靠、按序、可控制速率的字节流传输。