示意图
概要流程
TCP是全双工的通信协议,因此关闭连接通道的时候需要两边都关闭;发送FIN报文的一边仅表示这个方向没有数据流动,但是另一个方向可能还有,除非它也发送FIN报文。现在假设客户端先执行关闭TCP连接通道的动作:
第一次挥手
当客户端已经没有数据需要继续发送给服务端时,会发送一个FIN报文给服务端,此时该方向不会有数据传输;即客户端告诉服务端:“我已经没有数据要发送给你了,想要关闭TCP连接通道。”
第二次挥手
服务端接收到FIN报文后知道客户端期望关闭TCP连接通道的意图,会回应一个ACK报文进行确认;同时继续处理一些还未完成的响应动作等,此时服务端还是可以继续发送数据给客户端。即服务端告诉客户端:“我知道了,但是我还有些工作要完成,有些数据还需要传给你,等我消息 。”
第三次挥手
当服务端也没有需要发送给客户端的数据时,会发送一个FIN报文给客户端,此时该方向也将不会有数据传输了。即服务端也告诉客户端:“我也没有数据需要传给你了,也想关闭连接了。”
第四次挥手
客户端接收到FIN报文后会回应一个ACK报文给服务端,表明已经接收到服务端释放连接资源的请求,随后进入TIME_WAIT状态,等待2MSL(这个时间并不固定,一般设置是4min,即1MSL为2min;但Linux下1MSL是30s)时间后,若没有再次收到服务端发送的FIN报文则正式关闭TCP连接通道。
为什么要进行四次挥手,三次挥手可行不?
一般情况下都是进行四次挥手,因为每次挥手都有其自己的意义:
· 第一次挥手表明客户端没有数据发送给服务端,请求关闭连接通道;
· 第二次挥手表明服务端确认接收到客户端断开连接的请求;
· 第三次挥手表明服务端也没有数据要发送给客户端,请求关闭连接通道;
· 第四次挥手是客户端确认服务端关闭连接的请求;
这样进行四次挥手能够确保双方都完成了数据传输任务,不会出现数据丢失等问题,确认连接可靠关闭。而三次挥手无法保障这点,但也可能存在三次挥手的场景,比如开启了TCP延迟确认机制,即被动方可以延迟发送ACK报文,直到它也没有数据发送时可以将ACK确认报文和FIN报文进行合并发送以减少一次挥手。