1、四次挥手状态及消息类型
第一次挥手:假设客户端打算关闭连接,发送一个TCP首部FIN被置1的FIN报文给服务端。
第二次挥手:服务端收到以后,向客户端发送ACK应答报文。
第三次挥手:等待服务端处理完数据后,向客户端发送FIN报文。
第四次挥手:客户端接收到FIN报文后回一个ACK应答报文。
服务器收到ACK报文后,进入close状态,服务器完成连接关闭。
客户端在经过 2MSL一段时间后,自动进入close状态,至此客户端也完成连接的关闭。
2、为什么挥手需要四次?
- 关闭连接时,客户端发送FIN报文,表示其不再发送数据,但还可以接收数据。
- 服务端收到FIN报文,先回一个ACK应答报文,服务端可能还要数据需要处理和发送,等到其不再发送数据时,才发送FIN报文给客户端表示同意关闭连接。
从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK 和 FIN 一般都会分开发送,从而比三次握手导致多了一次。
第一次ACK应答报文可以省略,因为下一个报文段携带了ACK信息,ACK是否出现取决于延迟确认特性。
延迟确认:即接收方收到包后,如果暂时没有内容回复给发送方,则延迟一段时间再确认,假如在这个时间范围内刚好有数据需要传输,则和确认包一起回复。这种也被称为数据捎带。延迟确认只是减轻网络负担,未必可以提升网络性能,有些情况下反而会影响性能。
3、为什么 TIME_WAIT 等待的时间是 2MSL?
MSL是 Maximum Segment Lifetime,报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
等待MSL两倍:网络中可能存在发送方的数据包,当这些发送方的数据包被接收方处理后又会向对方发送响应,所以一来一回需要等待 2 倍的时间。
2MSL的时间是从客户端接收到 FIN 后发送 ACK 开始计时的。如果在 TIME-WAIT 时间内,因为客户端的 ACK 没有传输到服务端,客户端又接收到了服务端重发的 FIN 报文,那么 2MSL 时间将重新计时。
4、为什么需要 TIME_WAIT 状态?
需要 TIME-WAIT 状态,主要是两个原因:
- 防止具有相同四元组的旧数据包被收到;
- 保证被动关闭连接的一方能被正确的关闭,即保证最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭;
①有相同端口的 TCP 连接被复用后,被延迟的相同四元组的数据包抵达了客户端,那么客户端是有可能正常接收这个过期的报文,这就会产生数据错乱等严重的问题。
经过2MSL这个时间,足以让两个方向上的数据包都被丢弃,使得原来连接的数据包在网络中都自然消失,再出现的数据包一定都是新建立连接所产生的。
②最后的ACK如果丢失,客户端直接进入close,服务端一直在等待ACK状态。当客户端发起建立连接的SYN请求,服务端会发送RST报文回应,连接建立会关闭。
如果 TIME-WAIT 等待足够长的情况就会遇到两种情况:
- 服务端正常收到四次挥手的最后一个 ACK报文,则服务端正常关闭连接。
- 服务端没有收到四次挥手的最后一个 ACK报文时,则会重发 FIN关闭连接报文并等待新的 ACK报文。
5、TIME_WAIT 过多有什么危害?
过多的 TIME-WAIT 状态主要的危害有两种:
- 第一是内存资源占用;
- 第二是对端口资源的占用,一个 TCP 连接至少消耗一个本地端口;
如果发起连接一方的 TIME_WAIT 状态过多,占满了所有端口资源,则会导致无法创建新连接。