TCP为什么三次握手和四次挥手
三次握手
TCP建立连接的过程称为三次握手,发起TCP连接请求的一方称为主动打开,另一方则是被动打开,以下是三次握手的图解:
上图以客户端Client为主动打开的一方,服务端Server为被动打开的一方。
- 首先两者在建立连接之前都处于Close状态,当服务端端口资源空闲时进入Listen状态,说明已经准备好监听TCP连接请求了。
- 客户端首先向服务端发送一个SYN报文,SYN标志代表“请求建立新连接”。而此SYN包的序号Seq=x(x通常为1)。随后客户端进入SYN_SENT阶段。
- 服务端收到SYN报文后,结束Listen阶段,并给客户端返回一个确认报文。该报文的标志位是SYN和ACK,代表“确认客户端的报文 Seq 序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接”。此报文的序号Seq=y,确认号Ack=x+1,表示收到客户端的序号 Seq 并将其值加 1 作为自己确认号 Ack 的值,随后服务器端进入 SYN_RECV 阶段。
- 客户端收到服务器的确认报文后,同样会给服务器返回一个确认报文,表示收到了服务器的确认报文,并结束SYNC_SENT状态。该报文的标志位为ACK,序号Seq=x+1,表示收到服务器端的确认号 Ack,并将其值作为自己的序号值。确认号Ack=y+1,表示收到服务器端序号 seq,并将其值加 1 作为自己的确认号 Ack 的值。随后客户端进入ESTABLISHED状态。
- 服务端收到客户端的确认报文后,说明客户端也能正常收到服务端的报文,此时服务端结束SYNC_RECV状态,同样进入ESTABLISHED状态。
四次挥手
上图以客户端Client为主动关闭连接的一方,服务端Server为被动关闭连接的一方。
- 断开连接之前,客户端和服务端都处于ESTABLISHED状态,正常进行数据传输。
- 客户端主动发起关闭连接请求报文,该报文的标志位为FIN,表示“请求释放连接”,序号Seq=u(u为上一条报文的序号+1),随后客户端进入FIN_WAIT_1状态。
- 服务端收到关闭连接报文后,返回确认报文给客户端。该报文的标志位为ACK,序号Seq=v(v为上一条报文的序号+1),确认号Ack=u+1,表示收到客户端的序号 Seq 并将其值加 1 作为自己确认号 Ack 的值,随后服务端进入CLOSE_WAIT状态。
- 客户端收到确认报文后,进入FIN_WAIT_2状态,等待服务端把未发送完的数据全部发送完毕。
- 当服务端将之前为发送完的数据全部发送完毕后,结束CLOSE_WAIT状态并给客户端返回标志位为FIN和ACK的报文。该报文的序号Seq=w,确认号Ack=u+1,和上一条ACK报文的确认号一致,服务端进入LAST_ACK状态。
- 客户端收到FIN和ACK报文之后,确认服务器已经做好了断开连接的准备,结束FIN_WAIT_2状态,并给服务器返回确认报文,该报文的标志位为ACK,序号Seq=u+1,确认号Ack=w+1,随后客户端进入TIME_WAIT状态。
- 服务端收到客户端的确认报文后,结束LAST_ACK状态,进入CLOSE状态,断开连接。而客户端在TIME_WAIT状态下经过2MSL时间之后,也进入CLOSE状态,TCP四次挥手完毕。
为什么要三次握手,两次握手不行吗
三次握手的主要目的是确认自己和对方的发送和接收都是正常的,从而保证了双方能够进行可靠通信。若采用两次握手,当第二次握手后就建立连接的话,此时客户端知道服务器能够正常接收到自己发送的数据,而服务器并不知道客户端是否能够收到自己发送的数据。
为什么要四次挥手,三次挥手不行吗
释放 TCP 连接时之所以需要四次挥手,是因为 ACK 确认接收报文和FIN 释放连接报文是分别在两次握手中传输的。 当主动方在数据传送结束后发出连接释放的通知,由于被动方可能还有必要的数据要处理,所以会先返回 ACK 确认收到报文。当被动方也没有数据再发送的时候,则发出FIN释放连接报文,对方确认后才完全关闭TCP连接。若采用三次挥手,服务端直接在收到FIN报文后就回复FIN和ACK报文,那么客户端收到该报文后就不会再接收数据了,那服务端还没发完的数据就会丢失。