前言
当你打开浏览器访问网页、用聊天软件发消息时,背后其实有一个"隐形的管理者"在工作------它负责帮你的设备和目标服务器"打好招呼"、"按规矩传数据",最后"礼貌告别"。这个管理者,就是 TCP 的运输连接管理。
TCP 和 UDP 最大的区别在于"面向连接":UDP 像寄明信片,写完直接扔邮筒,不管对方收没收到;而 TCP 像打电话,要先等对方接起(建立连接)、说清楚要聊什么(协商规则)、聊完再挂电话(释放连接)。
- 接下来我们就一步步拆解这个"打电话"的全过程,让你搞懂 TCP 是怎么管理连接的。
我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343我的计算机网络专栏,欢迎来阅读
https://blog.csdn.net/2402_83322742/category_12909527.html
一、TCP 的运输连接管理
首先要明确:TCP 运输连接的生命周期分 3 个核心阶段,所有管理工作都是为了让这 3 个阶段"平稳落地"。
1.1 运输连接的三个阶段
TCP 连接从建立到结束,就像一次打电话的过程,分为 3 步:
阶段 | 核心作用(通俗理解) | 对应场景举例 |
---|---|---|
连接建立 | 双方"打招呼",确认对方在线 + 约定沟通规则 | 你拨打电话,对方接起后说"喂,能听到吗?",你回复"能听到" |
数据传送 | 按约定的规则双向传数据(不丢、不重、按顺序) | 你和对方互相说话,清晰且不抢话 |
连接释放 | 双方"说再见",释放占用的资源(如缓存、端口) | 你说"先这样,挂了啊",对方回复"好,再见",然后挂电话 |
运输连接管理的目标很简单:让这三步"不出错"------比如别出现"你以为对方在线,其实没接"(连接建立失败),或者"挂了电话还占着线路"(资源泄漏)的情况。
1.2 TCP 连接建立:要解决的 3 个关键问题
在"打招呼"阶段(连接建立),TCP 必须先解决 3 个问题,否则后续传数据会一团糟:
- 确知对方存在:你得确认服务器真的在线,而不是拨了个空号。就像打电话时,要等对方"喂"一声,才知道人在。
- 协商核心参数:双方要约定"怎么传数据"------比如一次最多传多少字节(最大窗口值)、要不要用更高效的传输优化(窗口扩大选项、时间戳选项)。这就像快递员和你约定"一次送 5 个包裹,放快递柜",避免后续送错或送不下。
- 分配资源:双方要腾出专门的"空间"(如缓存、连接表项)来存对方发来的数据。就像你要腾出家里的桌子放快递,快递员也要腾出货车的位置装你的包裹。
1.3 TCP 的连接建立:三报文握手("请求-确认-再确认")

为了解决上面 3 个问题,TCP 用了 三报文握手(Three-way Handshake)------简单说就是"发 3 条消息,完成连接"。我们用"浏览器(客户 A)访问百度服务器(服务器 B)"举例,一步步看过程:
(1) 先搞懂 3 个关键标志位
在讲握手前,先认识 TCP 报文中的 3 个"信号",后续所有操作都靠它们:
- SYN:"请求建立连接"的信号(相当于"喂,在吗?我要连你");
- ACK:"确认收到消息"的信号(相当于"我收到你的话了");
- seq:"数据包的序号"(相当于给每个消息编个号,确保对方不丢、不重复接收)。
(2) 三报文握手的详细过程

TCP 双方在握手时,会切换不同的"状态"来记录进度,我们结合状态一起看:
步骤 | 发送方 | 发送的消息内容 | 发送方状态变化 | 接收方 | 接收方状态变化 | 通俗解释 |
---|---|---|---|---|---|---|
1 | 客户 A | SYN=1(请求连接),seq=x(序号x) | CLOSED → SYN-SENT | 服务器 B | (初始 CLOSED → 先进入 LISTEN 状态,等待连接) | A 主动"敲门":"百度服务器,在吗?我要访问你,先给你发个序号 x" |
2 | 服务器 B | SYN=1(同意连接),ACK=1(确认收到x),seq=y(序号y),ack=x+1(下次我要收x+1及以后的) | LISTEN → SYN-RCVD | 客户 A | - | B 回复:"我在!收到你的序号 x 了,我也给你发序号 y,你下次给我发 x+1 就行" |
3 | 客户 A | ACK=1(确认收到y),seq=x+1(按约定发x+1),ack=y+1(下次我要收y+1及以后的) | SYN-SENT → ESTABLISHED | 服务器 B | SYN-RCVD → ESTABLISHED | A 再确认:"收到你的序号 y 了,我按约定发 x+1,你下次给我发 y+1 就行" |
握手结束后:进入数据传送阶段
当双方都进入 ESTABLISHED 状态,就意味着"连接已建立",可以开始双向传数据了------比如浏览器向服务器要网页数据,服务器向浏览器发 HTML 代码,这一步会严格按之前约定的"窗口大小""序号规则"来传,确保数据不丢、不重、按顺序。
为什么是"三握手",不是"两握手"?
很多人会问:为什么不能少一步?比如 A 发 SYN,B 发 SYN+ACK,然后直接连接?
- 答案是:避免"旧连接请求"浪费资源。
比如 A 之前发过一个"旧的 SYN 请求"(因为网络延迟,迟迟没到 B),后来 A 又发了一个"新的 SYN 请求",和 B 完成了连接、传完数据、释放了连接。这时候那个"旧的 SYN 请求"突然到了 B,B以为是新请求,就会发 SYN+ACK 并等着 A 回复。如果是两握手,B 会直接进入连接状态,但 A 根本没发新请求,不会回复,B 的资源(缓存、端口)就会被一直占用,造成浪费。
而三握手时,A 看到"旧的 SYN+ACK"会忽略,不发第三次 ACK,B 等不到 ACK,就会释放资源,避免浪费。
1.4 TCP 的连接释放:四报文握手("我要关-确认-我也要关-确认")

数据传完后,TCP 不能"直接挂电话",因为它是双向通信------比如 A 说完了要挂,但 B 可能还有最后一点数据要发给 A(比如服务器还有个"结束响应"要发),所以需要"四报文握手"(Four-way Wavehand),让双方都能"体面告别"。
还是用"浏览器 A 和服务器 B"举例,看释放过程:
(1) 四报文握手的详细过程

步骤 | 发送方 | 发送的消息内容 | 发送方状态变化 | 接收方 | 接收方状态变化 | 通俗解释 |
---|---|---|---|---|---|---|
1 | 客户 A | FIN=1(请求释放连接),seq=u(当前序号u) | ESTABLISHED → FIN-WAIT-1 | 服务器 B | - | A 说:"我数据传完了,要关连接了,最后给你发序号 u" |
2 | 服务器 B | ACK=1(确认收到u),seq=v(当前序号v),ack=u+1(下次收u+1及以后) | ESTABLISHED → CLOSE-WAIT | 客户 A | FIN-WAIT-1 → FIN-WAIT-2 | B 回复:"收到你的关闭请求了,我先处理下剩下的数据,你等我一下" |
3 | 服务器 B | FIN=1(我也要释放连接),seq=w(处理完数据后的序号w),ack=u+1 | CLOSE-WAIT → LAST-ACK | 客户 A | - | B 说:"我数据也传完了,现在要关连接了,最后给你发序号 w" |
4 | 客户 A | ACK=1(确认收到w),seq=u+1(按约定发u+1),ack=w+1 | FIN-WAIT-2 → TIME-WAIT | 服务器 B | LAST-ACK → CLOSED | A 回复:"收到你的关闭请求了,我等一会儿再关,你先关吧" |
(2) 关键:A 必须等待 2MSL 的时间(TIME-WAIT 状态的意义)
在步骤 4 后,A 不会马上进入 CLOSED 状态,而是会进入 TIME-WAIT 状态 ,并等待 2MSL(Maximum Segment Lifetime,报文段最大生存时间)------通常 MSL 是 30 秒或 1 分钟,所以 2MSL 就是 1~2 分钟。
为什么要等这 2 分钟?核心是"双保险":
- 确保 B 能收到最后一个 ACK:A 发的最后一个 ACK 可能丢了,B 没收到会重发 FIN。A 等 2MSL,就能收到 B 重发的 FIN,然后再重发一次 ACK,避免 B 一直等 ACK 而不释放资源。
- 避免旧报文干扰新连接:A 等 2MSL,能让本连接中所有"飘在网络里的旧报文"(比如延迟的数据包)都失效。这样下次 A 再和 B 建立新连接时,不会遇到这些旧报文,避免搞混数据。
当 2MSL 时间到,A 才会从 TIME-WAIT 进入 CLOSED 状态,至此整个 TCP 连接完全释放。
(3) 为什么是"四挥手",不是"三挥手"?
因为 TCP 是双向的,B 收到 A 的 FIN 后,可能还有数据要传(比如步骤 2 到步骤 3 之间的"处理剩下的数据"),不能马上发 FIN,必须先回复 ACK 表示"收到关闭请求",等数据传完再发 FIN。如果是三挥手,B 会把 ACK 和 FIN 合并成一条消息,但这样会导致 A 误以为 B 没有剩余数据,可能提前关闭,丢数据。
1.5 TCP 的有限状态机:连接的"操作手册"

前面讲了连接建立和释放时的状态变化,但 TCP 有哪些状态?什么时候会切换?用"有限状态机"(Finite State Machine)就能一目了然------它就像 TCP 的"操作手册",规定了"在什么条件下,从哪个状态切换到哪个状态"。
(1) 先认识 TCP 的 11 个核心状态

TCP 所有状态可以按"生命周期阶段"分类,避免记混:
状态分类 | 状态名称 | 状态含义(通俗解释) |
---|---|---|
初始/终止状态 | CLOSED | 连接未建立或已完全释放(相当于电话没拨,或已经挂了) |
监听状态 | LISTEN | 服务器处于"等待连接"状态(相当于百度服务器一直开着,等用户访问) |
连接建立相关 | SYN-SENT | 客户发了 SYN,等服务器的 SYN+ACK(相当于你拨了电话,等对方接) |
连接建立相关 | SYN-RCVD | 服务器收了 SYN,发了 SYN+ACK,等客户的 ACK(相当于对方接了电话,等你说话) |
数据传输状态 | ESTABLISHED | 连接已建立,可双向传数据(相当于你和对方正在聊天) |
连接释放相关 | FIN-WAIT-1 | 客户发了 FIN,等服务器的 ACK(相当于你说"要挂了",等对方回复) |
连接释放相关 | FIN-WAIT-2 | 客户收了服务器的 ACK,等服务器的 FIN(相当于对方说"知道了,等我说完",你等对方挂) |
连接释放相关 | CLOSE-WAIT | 服务器收了客户的 FIN,发了 ACK,等自己传完数据(相当于你说"要挂了",对方说"知道了",但对方还有话没说) |
连接释放相关 | LAST-ACK | 服务器发了 FIN,等客户的 ACK(相当于对方说"我也说完了,挂了",等你确认) |
连接释放相关 | CLOSING | 客户和服务器同时发 FIN(相当于你和对方同时说"要挂了",互相等 ACK) |
连接释放相关 | TIME-WAIT | 客户收了服务器的 FIN,发了 ACK,等 2MSL(相当于你确认对方要挂了,等一会儿再挂) |
(2)状态变迁的"核心流程"(结合三握手+四挥手)
有限状态机的箭头太多,我们只记"正常流程"(忽略异常情况),和之前的三握手、四挥手对应:
连接建立的状态链(客户 A + 服务器 B)
- 客户 A(主动打开):
CLOSED
→ 发 SYN →SYN-SENT
→ 收 SYN+ACK → 发 ACK →ESTABLISHED
- 服务器 B(被动打开):
CLOSED
→ 开启监听 →LISTEN
→ 收 SYN → 发 SYN+ACK →SYN-RCVD
→ 收 ACK →ESTABLISHED
数据传输:稳定在 ESTABLISHED
状态
双方在这个状态下双向传数据,直到一方想释放连接。
连接释放的状态链(客户 A 先发起释放)
- 客户 A(主动关闭):
ESTABLISHED
→ 发 FIN →FIN-WAIT-1
→ 收 ACK →FIN-WAIT-2
→ 收 FIN → 发 ACK →TIME-WAIT
→ 等 2MSL →CLOSED
- 服务器 B(被动关闭):
ESTABLISHED
→ 收 FIN → 发 ACK →CLOSE-WAIT
→ 传完数据发 FIN →LAST-ACK
→ 收 ACK →CLOSED
特殊情况:同时关闭(CLOSING 状态)
如果客户 A 和服务器 B 同时发 FIN,那么 A 会从 FIN-WAIT-1
进入 CLOSING
状态(而不是 FIN-WAIT-2),B 也会从 ESTABLISHED
进入 CLOSING
状态;等双方都收到对方的 ACK 后,再进入 TIME-WAIT
状态,最后到 CLOSED
。
(3)常见异常状态变迁(了解即可)
SYN-SENT
→CLOSED
:客户发了 SYN 后,等了很久没收到回复(超时),主动关闭。LISTEN
→CLOSED
:服务器关闭监听(比如百度服务器维护,暂时不接受新连接)。SYN-RCVD
→CLOSED
:服务器收了 SYN 后,等了很久没收到客户的 ACK(超时),释放资源。
以上就是本篇博客的全部内容,下一篇我们继续探讨计算机网络里面的知识。
我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343我的计算机网络专栏,欢迎来阅读
https://blog.csdn.net/2402_83322742/category_12909527.html
|------------------------------------|
| 如果您觉得内容对您有帮助,欢迎点赞收藏,您的支持是我创作的最大动力! |
