随笔分类
四次挥手
主要用于客户端与服务器端断开连接
第一次挥手:客户端表明自己没有消息发送,准备断开连接
第二次挥手:服务器端知道了客户端没有消息发送了,而自己还有消息要发送,请求客户端先别着急去断开连接
第三次挥手:服务器端也没消息发送了,发送断开连接的请求
- 由于网络是不可信的,断开连接的请求信号可能丢失,不丢失的话,客户端接收到后就会去断开连接,丢失的话,如果仅仅是三次挥手的话,服务器端发送完消息后就断开了连接,而客户端就一直等待着后续消息的发送,即 "空等待",白白浪费了资源
- 即三次挥手的话,服务器端是无法确保客户端已经知道自己要断开连接了
第四次握手:客户端返回已经知道了服务器端要断开连接的消息,然后服务器端接收后,就真的去断开了连接
TimeWait
time_wait出现在四次挥手中
先来粗略看下,四次挥手的图:
C S
Fin_Wait_1 --->
<---- Close_Wait
Fin_Wait_2
<---- Last_Ack
首先客户端向服务端发送 Fin
标志位,表示要进入关闭连接了,客户端进入 Fin_Wait_1
状态
服务端向客户端发送 Ack
信号,表示已经接收到关闭连接的请求,但是可能还有一部分数据没有发送完毕,服务器端进入 Close_Wait
状态;客户端接收到 Ack信号后进入 Fin_Wait_2
状态
等待服务器把数据传输完毕后,向客户端发送 Fin、Ack
标志,表示已经发送完剩下的数据了,准备去断开连接;此时服务端进入 Last_Ack
状态,客户端接收后进入 Time_Wait
状态
客户端向服务端发送 Ack
标志,表示自己已经接受到关闭连接的请求了;在等待 2倍的最大传数据长度之后 (2MSL),客户端会关闭
- 如果服务器端出现大量的
Time_Wait
状态,表示服务端可能在此次连接中扮演客户端的角色,去访问另一个服务器 - 另外,由于连接数量关闭多时,默认的 2MSL太长,可能会存在大量 time_wait状态,此时可以通过调整 time_wait等待的时间来减少出现 time_wait的数量
MSL
MSL是 TCP的 报文的最大生存时间
四次挥手为什么要等 2个 MSL,而不是 1个 MSL?
等待 2MSL时间的最主要目的是怕最后一个 ACK包对方没收到 (客户端是无法知道服务端有没有接收到 ACK
包的),那么对方在超时后将会去重发第三次挥手的 FIN包,此时客户端接收到 FIN包后再发一个 ACK应答包,此时客户端又会去等待 2MSL,直到足够的时间内没有再接收到 FIN,说明 ACK成功到达,此时客户端也会去关闭连接
为什么不直接关闭要进入等待状态呢?
主要是来保证客户端发送的 ACK报文段能够到达服务端,从而保证 tcp连接能够进行正常可靠的关闭
若客户端在发送 ACK
后就立即关闭了,且 ACK
丢失的情况,服务端就会一致处于等待关闭的状态,超时后再去发送关闭请求,那么服务器端就无法进行正常的关闭了