摘要
- TCP断开连接
- TIME_WAIT
- TIME_WAIT优化
- TCP保活
- Sokcet编程
文章插图
- 客户端会发送一个FIN报文给服务端 , 然后进入FIN_WAIT_1状态
- 服务端在收到FIN报文后 , 会回复客户端段一个ACK报文 , 然后进入CLOSED_WAIT状态
- 客户端在收到服务端的ACK报文以后会进入FIN_WAIT_2状态
- 服务端在处理完历史数据以后会发送FIN报文给客户端 , 然后进入LAST_ACK状态
- 客户端在收到服务端的FIN报文以后 , 会发送一个ACK报文给服务端 , 然后进入TIME_WAIT状态
- 服务器在收到ACK报文以后 , 就会真正的关闭连接 , 进入CLOSED状态
- 客户端在经过2MSL时间后 , 也会自动关闭连接进入CLOSED状态
原因是客户端在主动发起FIN报文以后仅表示客户端不再主动发送数据了但是还可以接收数据 。服务器在响应ACK报文以后 , 还有可能有数据还在处理且需要发送给客户端 , 因此当服务器处理完这些数据以后才能发送FIN报文表示同意关闭连接 。
因此服务端的ACK和FIN报文需要分开发送 , 挥手也就变成了4次 。
什么是MSL和TTL
TTL是IP头部中的一个字段 , 是指IP数据报可以经过的最大路由数 , 每经过一个路由器都需要减1 , 当TTL值为0时数据报就会被丢弃 , 同时发送ICMP报文给源主机 。TTL的单位是路由跳数 。
MSL是报文在网络中存在的最长时间 , 超过该时间就会被丢弃 。
为什么TIME_WAIT需要经历2MSL后才可以变为CLOSED
网络中存在的发送方数据包 , 首先需要发送给服务端 , 服务端在处理完以后又会将相应发送给客户端 , 所以总共需要2个倍的时间 。
2MSL的时间是从客户端接收到FIN报文并且发送ACK报文时开始的 。如果此时ACK报文没有被服务端接收到触发了服务端的超时重传 , 客户端又再次收到了FIN报文 , 那么2MSL将重新开始计时 。
linux中默认一个MSL是30s , 也就是说TIME_WAIT的时间是60s 。
TIME_WAIT为什么需要TIME_WAIT状态
主动发起连接中断的一方需要有TIME_WAIT状态 , 主要是以下原因:
- 防止具有相同四元组的旧数据包被收到
- 保证最后一次ACK报文能被被动关闭连接的一方收到 , 也就是保证被动关闭连接的一方能被正确关闭 。
文章插图
假设没有TIME_WAIT状态 , 如果有相同的端口的TCP连接被服用后 , 上图中被延迟SEQ=301的数据包抵达了客户端 , 客户端是有可能正常接收该报文的 , 此时就会产生数据错乱现象 。
但通过2MSL的等待时间 , 通信双方的数据包都可以在网络中消失 , 新的数据包一定是新连接的 。
保证连接正确关闭
通过等待2MSL的时间确保最后一次ACK报文被被动断开连接的一方收到 , 从而正常关闭 。
文章插图
上图如果服务端没有收到最后一个ACK报文会处于LAST_ACK状态 , 如果此时客户端发起了一个新的SYN报文请求建立连接 , 服务端会发送RST报文给客户端 , 连接建立失败 。
但是通过等待2MSL的时间会解决上述问题 , 因为假设服务端没有收到最后一次ACK报文 , 会触发超时重传重新发送FIN报文并等待新的ACK报文 。客户端在收到新的FIN报文时会重新发送ACK报文并刷新2MSL的计时 , 最终能够保证服务端的连接能够正常关闭 。
TIME_WAIT过多的弊端
服务器如果有TIME_WAIT状态的连接 , 说明TCP连接的断开是由服务端发起的 , 此时如果TIME_WAIT的连接过多 , 将会出现以下问题:
推荐阅读
- 一文弄懂Redis缓存一致性最佳实践参考案例
- 电脑残留垃圾清除:执行1行代码轻松搞定!无需杀毒软件
- 红茶的历史,遵义红茶的起源
- 一文看穿跨域BGP/MPLS IP VPN三方案
- 一文读懂Access数据库,从此不用Access数据库
- 手把手带你找到她电脑的wifi密码
- 一文详解Liquibase如何自动化数据库脚本部署
- 一文带你搞定TCP连接队列
- 微软|Win11中的祖传UI从Win9X流传至今!一文了解详情
- 一文看懂编程的本质,程序员有前途么?