近日无意间发现了一个小窍门:当TCP连接所对应socket的接收队列中仍有未读数据时,将此socket强行close后,将使此socket连接不会进入TIME_WAIT状态,用"netstat -anp"命令查看可发现此连接将消失的无影无踪!上述情形在linux2.6.18-5-686-bigmem内核及winxp平台上验证通过。其他平台上,以及当socket的发送队列中仍有剩余数据未发送时强行close后是否可重现此现象,尚未进行验证。
       那么说了这么多,这个窍门有什么用呢?对TCP的socket编程比较熟悉的人都知道,通常情况下,当一个socket已成功地在服务端和客户端建立连接后,无论是哪一方,先行调用close的那一方所对应的socket最终必会进入TIME_WAIT状态,并且会持续2*MSL,大约1-4分钟,然后由操作系统自动回收并将TCP连接设为CLOSED初始状态。这个过程按下图中的TCP连接状态转换过程进行:

在socket的TIME_WAIT状态结束之前,该socket所占用的本地端口号将一直无法释放。编写过高TCP并发并且采用短连接方式进行通讯的软件程序的人,都可能体会到,这样的通讯系统在高并发高负载下运行一段时间后,就常常会出现做为客户端的程序无法向服务端建立新的socket连接的情况。此时用"netstat-anp"命令查看系统将会发现机器上存在大量处于TIME_WAIT状态的socket连接,并且占用大量的本地端口号。最后,当该机器上的可用本地端口号被占完,而旧的大量处于TIME_WAIT状态的socket尚未被系统回收时,就会出现无法向服务端创建新的socket连接的情况。此时的通讯系统几乎停转,空有再好的性能也发挥不出来。
       如果能够在客户端程序主动关闭socket之前,让该socket的接收队列中仍保留一些数据(至少要有多余的一个字节的数据),然后调用close关闭,那么上述的无法向服务端创建新的socket连接的情况将不会出现。这是因为当socket的接收队列中仍有数据未被应用程序读走就被强行关闭时,操作系统(至少在笔者验证过的操作系统上的确如此)的TCP/IP协议栈驱动程序会在底层主动向服务端发送一个要求结束TCP连接的控制包,并将该TCP包头的flag控制字段中的RESET位置位,从而迅速结束了此TCP连接。这其实是操作系统对TCP连接断开的一种异常处理。而正常情况下(socket的接收队列中无未读数据),当应该程序调用close关闭连接时,底层驱动程序向服务端发送的要求结束TCP连接的控制包头的flag控制字段中是将FIN位置位,并且严格遵循上图所示的状态转换过程,最终到达TIME_WAIT状态并持续2*MSL的时间。
       知道了上述原理,具体如何利用呢?这有两种思路。第一种,从服务端入手,在服务端向客户端返回所有有效数据后,再在后面插入若干填充字节;而在客户端将有效数据读完之后,将填充字节留在对应socket的接收队列中,然后直接关闭连接。这个思路的好处是对客户端程序不需要做改动。第二种思路是从客户端入手,在客户端程序中控制从socket的接收队列中recv数据的节奏,将最后一个有效字节留在接收队列中不取出。但是怎么知道哪里是最后一个字节呢?最后一个字节的内容是什么?解决第一个问题的方法就是制定客户端与服务端通讯协议时应该考虑提供某种机制,让客户端解包时能够知道数据包何时结束,例如可以在通讯包的头部指示整个包的长度。解决第二个问题的方法是调用recv时使用MSG_PEEK标志,例如:
        ssize_t recvBytes = recv(socket,buf,buflen,MSG_PEEK);
当以MSG_PEEK标志接收数据时,数据将只从socket的接收队列中拷贝到指定的buf中,而相应的数据不会被移出接收队列。这样就能够既获得应用程序所需数据,又能将数据留在socket接收队列中,进而能够在关闭时使该TCP连接不进入TIME_WAIT状态。第二种思路的好处是不需要对服务端程序进行改动。笔者已将第二种思路实现并验证可行。
       
备注:在网上,解除TIME_WAIT状态限制有多种方法,其中有种方法是在socket建立后调用setsockopt函数如下:
       int option = 1;
       setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
如此就可以解决问题了。但实际上,有的平台不支持setsockopt函数,既使是在能够支持的平台,笔者经实际验证发现并不能达到目的。另有一些其他方法也各有利弊。所以,如果其他方法无效,本文中的方法就值得一试了。

一个解除TCP连接的TIME_WAIT状态限制的简便方法相关推荐

  1. 83998 连接服务器出错_服务端 TCP 连接的 TIME_WAIT 问题分析与解决

    民工哥技术之路 写在开头,大概 4 年前,听到运维同学提到 TIME_WAIT 状态的 TCP 连接过多的问题,但是当时没有去细琢磨:最近又听人说起,是一个新手进行压测过程中,遇到的问题,因此,花点时 ...

  2. 网络:TCP通讯之 time_wait 状态

    基于TCP协议的通讯流程 1.TCP建立连接 2.TCP断开连接 3.TCP状态转换 TCP状态解释: SYN-RECVD:再收到和发送一个连接请求后等待对方对连接请求的确认 ESTABLISHED: ...

  3. 基础原理系列:服务端 TCP 连接的 TIME_WAIT 问题

    几个方面: 问题描述:什么现象?什么影响? 问题分析 解决方案 底层原理 1.问题描述 模拟高并发的场景,会出现批量的 TIME_WAIT 的 TCP 连接: 短时间后,所有的 TIME_WAIT 全 ...

  4. close wait 过多原因_干货分享!服务端 TCP 连接的 TIME_WAIT 问题分析与解决

    写在开头,大概 4 年前,听到运维同学提到 TIME_WAIT 状态的 TCP 连接过多的问题,但是当时没有去细琢磨:最近又听人说起,是一个新手进行压测过程中,遇到的问题,因此,花点时间,细深究一下. ...

  5. linux服务器上tcp有大量time_wait状态的解决方法和原因解释

    在检查服务器时,发现有很多连接超时情况出现,用netstat命令查看,tcp的time_wait状态较多,需要进行优化. 1. 看一下现在time_wait的数量 netstat -an | grep ...

  6. TCP连接中time_wait在开发中的影响-搜人以鱼不如授之以渔

    根据TCP协议定义的3次握手断开连接规定,发起socket主动关闭的一方socket将进入TIME_WAIT状态,TIME_WAIT状态将持续2个MSL(Max Segment Lifetime),T ...

  7. TCP连接中TIME_WAIT连接过多

    2019独角兽企业重金招聘Python工程师标准>>> TCP连接中TIME_WAIT连接过多 转载于:https://my.oschina.net/meowmeow/blog/36 ...

  8. TCP连接(Time_Wait、Close_Wait)说明

    修改Time_Wait和CLOSE_WAIT时间 修改Time_Wait参数的方法 (在服务端修改) Windows下在HKEY_LOCAL_MACHINE/SYSTEM/CurrentControl ...

  9. 介绍一个查看TCP连接的工具TCPView

    该工具可以帮助使用者查看该机器上建立的所有的TCP连接, 以及TCP连接所使用的端口信息, 连接的状态信息, 进程ID等. 还可以看到连接过来的对方的机器名, 端口号. 在工具窗体下方的工具栏里, 还 ...

最新文章

  1. PHP性能调优---php-fpm - 启动参数及重要配置详解
  2. java web服务与配置,Java Web远端服务器的配置与部署
  3. jdk 取整数_JDK 15中的确切绝对整数
  4. 【转】无刷新验证用户名可用性
  5. MyBatis源码之:MapperMethod
  6. 判断手机是否支持闪光灯的
  7. C++编程技术常见问题有哪些?
  8. 思科6509的详细配置---加注释
  9. create-react-app 支持多入口
  10. axure 倒计时_Axure 8.0实例 |自定义倒计时制作流程
  11. 深入了解JVM之内存区域(一)
  12. 2021-3-17 Jmeter线程组、运行启动方式
  13. Android代码中实现WAP方式联网
  14. 杭州java校园招聘_网易校园招聘杭州Java笔试题
  15. UE4蓝图流程控制:FlipFlop节点、DoOnce节点的使用
  16. 深圳市半导体行业协会会长周生明率队赴加速科技调研
  17. 1.《The Leon Professional》
  18. “丧心病狂”的C语言小程序,拿去恶搞好友
  19. “三通”搭桥 两岸IT产业迎机遇
  20. python模拟登录详细教程_Python模拟登录requests.Session应用详解

热门文章

  1. shardingsphere 分片策略_ShardingSphere系列(二) 分片策略
  2. linux 添加接口永久,在Linux中,配置虚拟网络接口
  3. pandas 读取/保存压缩格式的csv文件.csv.gz
  4. Networdx小案例学习
  5. c语言微秒级延迟程序,C语言中生产随机数及计算运行时间(微秒级)
  6. zb如何导出自己画的_如何科学管理zb文件
  7. activiti创建子流程_OA流程图绘制指南
  8. JDK1.8版本,java并发框架支持锁包括
  9. seg代码配置的踩坑记录
  10. 卡尔曼滤波的基本原理