TCP四次挥手详解
一、四次挥手的过程
如上图所示,TCP四次挥手的过程为
- 客户端进程发出连接释放的报文,并且停止发送数据。报文的内容为,结束标志位FIN = 1, 序列号seq = u。 报文发送完成后,客户端由ESTABLISHED状态进入FIN-WAIT-1状态。(注意,TCP规定FIN报文即使不携带数据,也要消耗一个序列号)
- 服务器收到连接释放的报文后,发出确认报文。报文内容为,确认标志位ACK = 1, 确认号Ack = u+1, 序列号seq = v。报文发送完成后,服务器由ESTABLISHED状态进入CLOSE-WAIT状态。此时客户端已经不再向服务器发送数据,客户端向服务器方向的连接就释放了。但是服务器仍然能够向客户端发送数据,当前处于一种半关闭状态。
- 客户端收到服务端的确认报文后,由FIN-WAIT-1状态进入FIN-WAIT-2状态,等待服务器的数据发送完,等待服务器发出的连接释放报文。
- 服务器的数据发送完后,就向客户端发送连接释放报文。报文内容为,结束标志位FIN = 1, 序列号 seq = w, 确认标志位ACK = 1, 确认号 ack = u+ 1. 由于处于半关闭状态,服务器有可能又发送了一些数据。 报文发送完成后,服务器由CLOSE-WAIT状态进入LAST-ACK状态。
- 客户端收到服务器的释放连接报文后,发出确认报文。报文内容为,确认标志位ACK = 1, 确认号ack = w + 1,序列号 seq = u+1. 确认报文发送完成后,客户端由FIN-WAIT-2状态进入TIME-WAIT状态,等待2MSL的时间。(2个最长报文寿命的时间)
- 服务器收到客户端的确认报文后,有LAST-ACK状态进入CLOSED状态。等2MSL时间到后,客户端由TIME-WAIT状态进入CLOSED状态。此时,才完成了TCP链接的真正断开。
二、一些问题
1.为什么断开TCP连接需要四次挥手?
因为TCP连接是全双工的网络协议,它允许同时通信的双发同时进行数据的收发,同样也允许收发两个方向的连接被独立的关闭。所以TCP连接的断开需要四次挥手,每次关闭一个方向上的连接需要FIN和ACK两次挥手。
2.为什么TIME-WAIT状态需要2MSL的等待时间?
因为网络有可能使不可靠的。在客户端向服务器发送确认报文时,该确认报文可能会丢失。如果客户端发送完确认报文后进入CLOSED状态,而确认报文又丢失了,服务器端收不到客户端发送过来的确认报文便会一直向客户端发送连接释放报文(也就是第三次挥手的过程),可是此时客户端已经进入到CLOSED状态了呀,所以这个TCP连接永远都断不开了,一直在消耗服务端的性能。 但是如果客户端在发送完确认报文后有一个2MSL的TIME-WAIT状态,便完美的解决了这个问题。 为什么是2MSL呢? 因为发送报文和收到报文所需的最大时间是2MSL,在这段时间内,如果客户端没有重新收到服务端发来的请求连接释放的报文,就会默认客户端已经收到了确认报文。如果重新收到了服务器发送的请求连接释放的报文,客户端会重新回复一个确认报文,并重新进入一个2MSL的TIME-WAIT状态。
|