TCP 三次握手四次挥手:我画了六张图,终于讲清楚了
一、先搞清楚:TCP 连接是什么?
很多人把TCP连接想得很玄乎,其实它的本质很实在:通信双方在内核里各自维护了一组状态和缓冲区。所谓建立连接,说白了,就是双方就“我能收到你、你能收到我”这件事,达成一个可靠的共识。
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
这个过程,全靠数据包头部那几个关键标志位来驱动:
SYN —— 我想建立连接
ACK —— 我确认收到了你的包
FIN —— 我要关闭连接了
RST —— 直接重置,出问题了
理解了这几个信号,接下来的握手和挥手,就全是逻辑推演了。
二、三次握手:不是仪式,是必要条件
先看完整的流程图解,有个全局印象:

具体来说,这三步是这样的:
第一次握手:客户端主动出击,发送一个SYN包,核心意思是“我想建连接,我的初始序号是x”。发完这个包,客户端自己就进入SYN_SENT状态,开始等待回应。
第二次握手:服务端收到SYN后,如果同意连接,就回一个SYN-ACK包。这个包有两层含义:一是确认客户端的SYN(ACK),二是也发出自己的连接请求(SYN),并带上自己的初始序号y。此时,服务端进入SYN_RCVD状态。
第三次握手:客户端收到服务端的SYN-ACK后,发出最后一个ACK包进行确认。这个ACK包送达后,双方才共同进入ESTABLISHED状态,连接至此正式建立,可以开始传输数据了。
三、灵魂拷问:为什么不能两次握手?
这是面试官最爱追问的问题,也是理解TCP设计精髓的关键。光背“防止已失效的连接请求”不够,得看场景。
想象一个网络延迟极高的场景:客户端发了一个连接请求(SYN),但迟迟没收到回复,于是超时重发了一个新的。那个旧的SYN包其实没丢,只是在网络里“迷路”了。如果TCP设计成两次握手——即服务端收到SYN后,回一个SYN-ACK就直接建立连接——那么当那个“迷路”的旧SYN包很久之后终于到达服务端时,服务端会认为这是一个新的连接请求,直接建立连接并分配资源。
但问题是,客户端那边早就放弃这个旧请求了。结果就是,服务端会一直空等,白白消耗着连接资源。这就是著名的“已失效连接请求”问题。
所以,第三次握手那个ACK至关重要。它让服务端能够确认:“刚才发SYN的那个客户端,确实还在线,并且确实收到了我的回复,真想建立这个连接。”没有这第三次确认,服务端就无法区分当前收到的是一个正常的连接请求,还是一个迟到的、早已失效的旧请求。
四、序列号 seq 是什么?

握手过程中交换的序列号(seq)是干嘛的?它主要有两大使命:保证数据有序和检测重复包。
你可能会问,为什么不从0开始,非要弄个随机数作为初始序列号(ISN)?这同样是为了应对网络中的“历史遗留问题”。如果每次连接都从0开始序号,那么上一条连接残留在网络中的、序号重叠的“迷路包”,就可能被新连接错误地接收,导致数据混乱。使用随机化的ISN,可以极大降低这种新旧数据包序号冲突的概率,确保连接的独立性。
五、四次挥手:断开连接为什么比建立还麻烦?

断开连接需要四次交互,比建立连接多一步。原因其实很直接:TCP连接是全双工的。
建立连接时,双方的目标一致,都是开启通信通道,所以客户端的SYN和服务端的SYN-ACK可以“合并”在一次回复里。
但关闭连接时,情况不同了。“我不再发送数据了”和“我也不再发送数据了”是两个独立的、可能不同步的事件。当客户端发送FIN表示要关闭自己这一侧的发送通道时,服务端可能还有数据没传完。所以,服务端必须先回一个ACK,确认收到了客户端的关闭请求,然后继续发送剩余数据。等所有数据都发送完毕后,服务端再发送自己的FIN,关闭自己这一侧的发送通道。正因为ACK和FIN不能像握手时那样同时发出,所以挥手过程自然就变成了四步。
六、TIME_WAIT 是什么?为什么等 2MSL?
这里是面试的加分项,也是实际运维中经常遇到的“坑”。主动关闭连接的一方(比如客户端,或者主动关闭连接的服务器),在发出最后一个ACK之后,并不会立即进入CLOSED状态,而是会进入一个TIME_WAIT状态,并等待2MSL的时间。

MSL(Maximum Segment Lifetime)指报文在网络中的最大存活时间,Linux下通常默认是60秒。等待2MSL,主要出于两个目的:
1. 确保最后一个ACK能到达对端:如果这个ACK丢失了,被动关闭方(服务端)会重发FIN。等待2MSL给了足够时间让这个重传的FIN到达,客户端可以再次回应ACK,从而保证连接能可靠关闭。 2. 让旧连接的报文彻底消散:等待2MSL时间,足以让这个连接产生的所有报文都在网络中消失,避免它们干扰后续新建的、可能复用相同四元组(源IP、源端口、目的IP、目的端口)的新连接。
生产环境的影响:对于高并发短连接的服务,如果服务器是主动关闭方,就会产生大量处于TIME_WAIT状态的连接,占用大量端口,可能导致新连接因无法绑定端口而失败。常见的解决方案是启用端口复用:
在代码层面,可以设置SO_REUSEADDR套接字选项:
// 服务端启动时设置 SO_REUSEADDR,允许复用 TIME_WAIT 状态的端口
int opt = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
或者在系统层面进行配置:
# 允许 TIME_WAIT 状态的 socket 复用
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
七、完整状态机:TCP 连接一生经历的所有状态

这张状态转换图值得仔细琢磨。图中清晰地展示了客户端(蓝色路径)和服务端(绿色路径)在连接生命周期中经历的不同状态。两条路径在ESTABLISHED汇合,共享数据传输的时光,又在关闭时于不同的步骤分道扬镳。理解这张图,TCP连接的生命周期就在你脑子里了。
八、用代码验证:亲眼看到状态变化
理论懂了,最好动手验证一下。用几个简单的命令就能观察TCP状态的变化:
# 终端1:启动一个简单的服务端
nc -l 8080
# 终端2:持续查看连接状态(使用ss命令更现代)
ss -tn state established
# 或者使用传统的netstat
# netstat -an | grep 8080
# 终端3:模拟客户端连接
nc 127.0.0.1 8080
# 此时在终端2,能看到 ESTABLISHED 状态的连接
# 在终端3按 Ctrl+C 断开连接后,再观察终端2,能短暂看到 TIME_WAIT 状态
如果想在程序中获取连接状态,可以使用getsockopt:
// 用 getsockopt 获取 TCP 连接信息
struct tcp_info info;
socklen_t len = sizeof(info);
getsockopt(fd, IPPROTO_TCP, TCP_INFO, &info, &len);
// info.tcpi_state 就是当前连接状态(数字对应 TCP_ESTABLISHED=1 等)
printf("TCP state: %d\n", info.tcpi_state);
九、高频面试题精析
Q:三次握手中,第三次 ACK 丢失会怎样?
服务端会一直处于SYN_RCVD状态。它会按照TCP的重传机制,多次重传SYN-ACK包(默认最多5次,间隔时间指数级增长)。如果此时客户端已经进入ESTABLISHED并开始发送数据,那么服务端收到数据包后,会“被动”地进入ESTABLISHED状态。如果始终没收到任何确认或数据,服务端最终会超时关闭这个半连接。
Q:为什么四次挥手不能合并成三次?
根本原因在于,服务端收到FIN时,可能还有数据要发送,所以ACK和FIN不能同时发出。但如果服务端在收到FIN时,恰好没有数据要发送了,那么它完全可以将ACK和自己的FIN合并成一个包发送,这就变成了“三次挥手”。Linux的延迟确认(Delayed ACK)机制有时就会促成这种合并。
Q:SYN Flood攻击是怎么利用握手过程的?
攻击者疯狂发送SYN包,但不回复服务端回应的SYN-ACK,导致服务端维护的半连接队列(SYN_RCVD状态)被占满,无法处理正常的连接请求。防御方法之一是开启SYN Cookie:服务端收到SYN后,不立即分配资源,而是生成一个特殊的序列号(Cookie)放在SYN-ACK中;只有收到携带正确Cookie的ACK时,才正式分配资源建立连接。
Q:close()和shutdown()触发挥手有什么区别?
close()减少文件描述符的引用计数,只有当计数归零时,才会触发TCP的关闭流程(发送FIN)。如果这个套接字被dup()复制过,调用一次close()并不会真正关闭连接。shutdown(fd, SHUT_WR)则不同,它会立即触发TCP的关闭流程,向对端发送FIN,而不管引用计数是多少。因此,想要可靠地、立即地发起四次挥手,应该使用shutdown()。
十、一图总结:三次握手 vs 四次挥手

十一、结语
说到底,TCP三次握手和四次挥手的每一步设计,都蕴含着对网络不可靠性的深刻理解和严谨应对:
- 三次握手,是在最小交互次数下,确保双向通信通道的可靠建立。
- 四次挥手,是由于全双工通信的特性,两个方向的关闭需要独立确认。
- TIME_WAIT状态,则是为了最后一个ACK的可靠交付,以及让旧连接的“幽灵”报文彻底消失,为新连接扫清道路。
把这些逻辑理清楚,下次再面对面试官,你就不再是背诵课本答案,而是可以清晰地画出状态图,讲出每一步背后的“为什么”。这才是真正掌握了TCP连接的核心。
热门专题
热门推荐
研途考研APP下载文件存储位置详解: 你是否遇到过这样的困扰:已经下载了研途考研的课程视频准备离线学习,却不知道文件具体保存在手机的哪个文件夹?无需烦恼,下载内容的存放路径其实非常明确。遵循以下清晰的步骤指引,你不仅能快速定位已下载的视频资料,还能高效地进行文件管理与离线观看。 第一步:进入个人中心
小K电商图是什么 做电商的朋友,想必都为拍产品图头疼过。找模特、租场地、协调拍摄,一套流程下来不仅成本高,周期还长。市场上有没有什么解法?这就不得不提小K电商图。 简单来说,这是一款由北京云舶科技打造的AI工具,专门用来生成高质量的电商图片。云舶科技的背景很有意思,它成立于2017年,两位创始人梅嵩
Majilabs io是什么 想批量发送邮件,又担心被当成垃圾邮件或者封号?这正是许多销售和营销人的痛点。Majilabs io应运而生,它是一款由AI深度驱动的销售发展代表(SDR)助手。简单来说,它能帮你轻松撰写高度个性化的邮件,大规模安排会议并推动成交,整个过程严格遵守谷歌等平台的规范,有效规
从 Select 到 Epoll:深入理解 Linux 高并发网络模型的核心演进 在服务器开发领域,有一个问题几乎成了面试官的“必考题”:“为什么 Nginx 能同时处理几万个并发连接?” 如果你的回答停留在“因为它用了 epoll”,那么下一个问题通常会接踵而至:“epoll 为什么比 selec
美联储降息预期“急转弯”:4月行动概率腰斩至15% 市场风向,说变就变。就在上周,交易员们还在热议美联储4月降息的可能性,概率一度被推高至30%。然而,纽约联储主席约翰·威廉姆斯的一席话,宛如一盆冷水,让这股乐观情绪迅速降温。他明确表示,未来几个月的通胀率将“远高于”3%的目标水平。此言一出,市场立





