为什么要挥手
上一节我们知道TCP是全双工传输类型,所以在断开链接也需要双方都断开连接才可以。断开连接需要保证2个要点
- 连接的双方都能断开
- 连接的双发数据都传输完成了
挥手的过程与状态
挥手分为四次
- 第一次挥手发生在客户端,由客户端发起,向服务端发送一个FIN=1,表明客户端要断开连接,并发送一个Seq=23456(随机的数字,此次请求的序列码)。发送完成后,客户端端状态由ESTABLISH 变为 FIN_WAIT_1
- 第二次挥手发生在服务端,接收到客户端的FIN请求,服务端需要应答:ACK=1,并发送应答值Ack=Seq(客户端发送的)+1=23457,这时服务端的状态由ESTABLISH状态变为CLOSE_WAIT状态
- 客户端收到服务端的ACK包,检查Ack无误将状态由FIN_WAIT_1改为FIN_WAIT_2状态
- 服务端继续发送未完成的数据给客户端,如果客户端接收到这些数据,还是需要给一些应答包
- 这时在服务端发生第三次挥手,服务端在确认所有的数据都发送完成了, 则向客户端发送FIN=1,请求断开连接,并发送Seq码值为222333(一个随机码)。发送后,服务端的状态由CLOSE_WAIT状态变为LAST_ACK状态
- 客户端收到该应答包,检查完成后,并回复ACK,数据项为ACK=1;Ack=Seq+1=222334.并将状态由FIN_WAIT_2改为TIME_WAIT
- 服务端收到客户端的应答项,检查完成后,将自己的状态由LAST_ACK改为CLOSED状态。服务端连接彻底断开
- 客户端再2MSL后,将TIME_WAIT状态改为CLOSED状态,至此,客户端和服务端的链接全部断开
四次挥手即为四次数据传输,但是两端的状态卻有7种,如下
- 客户端
第一次挥手后 ESTABLISH->FIN_WAIT_1
第二次挥手后 FIN_WAIT_1->FIN_WAIT_2
第三次挥手后 FIN_WAIT_2->TIME_WAIT
之后再通过2MSL后 TIME_WAIT->CLOSED - 服务端
第二次挥手后 ESTABLISH->CLOSE_WAIT
第三次挥手后 CLOSE_WAIT->LAST_ACK
第四次挥手后 LAST_ACK->CLOSED
为什么是四次
- 如果是一次 只能客户端自己断开
- 如果是两次 客户端申请断开,服务端再接受断开,服务端不能确定客户端是否已经断开了连接了
- 如果是三次 即服务端应答包和断开连接请求一次完成。如果服务端并没有处理完成所有的任务,则该次的请求不会成功,为了确保所有的任务成功完成,应答包和断开连接的请求需要分两次进行