Loading...

一文吃透TCP三次握手与四次挥手

阅读 ...

TCP的三次握手和四次挥手,说实话,即使背了很多很多遍,还是容易搞忘。

本文,就用最直白的话梳理一下,强化记忆。

首先,TCP是面向连接、保证可靠的传输层协议,和“发出去就不管”的UDP完全不一样。

所以,它在正式传数据前,必须先建立可靠的连接,这就是三次握手

数据传完要安全断开、不能丢数据,这就是四次挥手

三次握手

TCP 三次握手的目标,是让客户端与服务端互相确认双方的收发能力正常、同步双方的初始化序列号,最终建立一条可靠的 TCP 连接。

第一次握手

客户端向服务端发送一个 同步标志位(SYN=1)的同步报文,报文中携带了自己随机生成的初始化序列号。

发送完成后,客户端进入同步已发送(SYN_SENT)状态。

第二次握手

服务端收到客户端的同步请求后,会回复一个同步标志位(SYN=1)和确认标志位(ACK=1)都置1的同步确认报文。

这个报文里,确认号是客户端的初始化序列号 + 1,同时也会携带服务端自己随机生成的初始化序列号。

发送完成后,服务端进入同步已收到(SYN_RCVD)状态。

第三次握手

客户端收到服务端的同步确认报文后,会回复一个确认标志位(ACK=1)的确认报文,其中确认号是服务端的初始化序列号 + 1。

发送完成后,客户端直接进入连接已建立(ESTABLISHED)状态;

服务端收到这个确认报文后,也会同步进入连接已建立状态。

到这里,TCP连接就正式建立完成,双方可以开始正常传输业务数据了。

为什么是三次握手,不是两次?

两次握手只能保证客户端确认服务端的收发能力正常,服务端却没法确认客户端的接收能力是正常的。

官话那么多,举个例子好理解一点:

如果客户端发的同步标志位(SYN=1)报文在网络里滞留了,客户端自己都放弃了,但是,这个报文在滞留结束后,还是来到了服务端。

这种情况,如果是两次握手,服务端收到后就会直接建立连接,一直等着客户端发数据,但是,客户端根本就不认这个连接,也不会发数据,这样就白白浪费了服务端的资源。

而如果是三次握手,服务端收到滞留的SYN报文、回复SYN+ACK后,客户端根本不会回复第三次ACK,服务端收不到最终确认,就不会建立无效连接,完美规避了资源浪费的问题。

四次挥手

四次挥手的本质,是TCP全双工连接双向关闭过程。

因为TCP连接是全双工的,双方都能独立发送和接收数据,所以,断开的时候,必须保证双方的数据都完全传输完毕后,再安全断开连接,不能单方面说断就断。

第一次挥手

客户端发送一个结束标志位(FIN=1)的结束包,告诉服务端:

我的业务数据已经全部发完了,之后不会再发送数据了。

发送完成后,客户端进入结束等待1(FIN_WAIT_1)状态。

第二次挥手

服务端收到客户端的结束包后,立刻回复一个确认标志位(ACK=1)的确认包,其中确认号是客户端 FIN 报文的序列号 + 1。

发送完成后,服务端进入关闭等待(CLOSE_WAIT)状态;

客户端收到这个确认包后,就会进入结束等待2(FIN_WAIT_2)状态。

这里要注意:

这个阶段,客户端已经不会再发送数据了,但服务端如果还有没发完的业务数据,依然可以正常给客户端发送,客户端也会正常接收。

第三次挥手

等服务端把所有剩余的数据都发送完毕后,也会给客户端发送一个结束标志位(FIN=1)的结束包,告诉客户端:我的数据也全部发完了,之后也不会再发送数据了。
发送完成后,服务端进入最后确认(LAST_ACK)状态

第四次挥手

客户端收到服务端的结束包后,立刻回复一个确认标志位(ACK=1)的确认包,其中确认号是服务端FIN报文的序列号 + 1。

发送完成后,客户端进入时间等待(TIME_WAIT)状态,等待2MSL(最长报文寿命)的时间后,才会正式关闭连接;

而服务端只要收到这个确认包,就会直接关闭连接。

到这里,整个TCP连接就正式断开了。

为什么握手只要三次,挥手却要四次?

握手的时候,服务端的SYN(同步报文)和ACK(确认报文)可以合并在同一个包里发送,所以三次就够了;

但挥手的时候,服务端收到客户端的结束报文时,可能还有没发完的数据要继续传,所以只能先回复确认报文进行确认,等数据全部发完了,才能再发结束报文告诉客户端自己也可以关了。

ACK和FIN分开发送,自然就变成了四次。

本文由 iamxurulin 原创发布,转载请保留原文链接。
最后更新于 2026-08-23 17:21:42
关于作者与文章

本文为 iamxurulin 原创技术文章。如对内容有疑问或建议,欢迎在评论区交流讨论。

Coder_Studio - 记录后端开发、算法与 AI 的成长之路