一、建立连接的过程(三次握手)
因为要保持连接和可靠性约束,TCP协议要保证每一条发出的数据必须要返回,而返回的数据叫做ACK(也就是响应)。
- 客户端(Client)发送连接请求给服务端(SYN),SYN是TCP/IP建立连接时使用的握手信号
- 服务端(Server)接收请求后回复ACK报文,并为这次连接进行连接分配资源,服务端进行查看是否收到了客户端的请求消息。
- 客户端(Client)确认接收到ACK报文后也向服务端(Server)发出ACK报文,并分配资源,即双方确定消息互通后同时建立连接相互通信。
为什么需要第三次通信 ?
1、在第一次通信过程中,A向B发送信息之后,B收到信息后可以确认自己的收信能力和A的发信能力没有问题。
2、在第二次通信中,B向A发送信息之后,A可以确认自己的发信能力和B的收信能力没有问题,但是B不知道自己的发信能力到底如何,所以就需要第三次通信。
3、在第三次通信中,A向B发送信息之后,B就可以确认自己的发信能力没有问题。
4、 小结:3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
二、断开连接的过程(四次挥手)
- 第一次挥手:客户端(Client)发送一个FIN(请求连接终止:FIN = 1),报文中会指定一个序列号 seq = u,用来关闭客户端(Client)到服务端(Server)的数据传送,主动关闭 TCP 连接,客户端(Client)进入FIN_WAIT_1状态,等待服务端确认。
- 第二次挥手:服务端(Server)收到FIN后,发送一个ACK报文给客户端(client),且把客户端的序号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端(Server)处于
CLOSE_WAIT
状态。 - 第三次挥手:如果服务端也想断开连接了(没有要向客户端发出的数据),和客户端的第一次挥手一样,发送 FIN 报文,且指定一个序列号,用来关闭Server到Client的数据传送。此时服务端处于
LAST_ACK
的状态,等待客户端的确认。第四次挥手:客户端收到 FIN 之后,Client进入TIME_WAIT状态,发送ACK给Server,Server进入CLOSED状态,完成四次握手。一样发送一个 ACK 报文作为应答(ack = w+1),且把服务端的序列值 +1 作为自己 ACK 报文的序号值(seq=u+1),此时客户端处于
TIME_WAIT
(时间等待)状态。其中:
FIN-WAIT-1
- 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;CLOSE-WAIT
- 等待从本地用户发来的连接中断请求;FIN-WAIT-2
- 从远程TCP等待连接中断请求;LAST-ACK
- 等待原来发向远程TCP的连接中断请求的确认;TIME-WAIT
- 等待足够的时间以确保远程TCP接收到连接中断请求的确认;
图中符号的意思:
FIN
:连接终止位seq
:发送的第一个字节的序号ACK
:确认报文段ack
:确认号。希望收到的下一个数据的第一个字节的序号
为什么连接的时候是三次握手,关闭的时候却是四次握手?
- ①TCP 是一个双工协议,当Server端收到Client端的SYN连接请求报文后,为了让双方都保证,建立连接的时候,双方可以直接向对方发送 SYN(同步请求)和 ACK(响应)。其中ACK报文是用来请求响应的的,SYN报文是用来同步请求的。
- ②但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。握手阶段双方都没有烦琐的工作,因此一方向另一方发起同步(SYN)之后,另一方可以将自己的 ACK 和 SYN 打包作为一条消息回复,因此是 3 次握手——需要 3 次数据传输。
- ③只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。到了挥手阶段,双方都可能有未完成的工作。收到挥手请求的一方,必须马上响应(ACK),表示接收到了挥手请求。类比现实世界中,你收到一个 Offer,出于礼貌你先回复考虑一下,然后思考一段时间再回复 HR 最后的结果。最后等所有工作结束,再发送请求中断连接(FIN),因此是 4 次挥手。
TCP的三次握手一定能保证传输可靠吗?
不能:
- 三次握手比两次更可靠,但也不是完全可靠,而追加更多次握手也不能使连接更可靠了。因此选择了三次握手。
- 世界上不存在完全可靠的通信协议。从通信时间成本空间成本以及可靠度来讲,选择了“三次握手”作为点对点通信的一般规则。