CLOSE_WAIT状态的生成原因
首先我们知道,如果我们的Client程序处于CLOSE_WAIT状态的话,说明套接字是被动关闭的!
因为如果是Server端主动断掉当前连接的话,那么双方关闭这个TCP连接共需要四个packet:
       Server ---> FIN ---> Client
       Server <--- ACK <--- Client
    这时候Server端处于FIN_WAIT_2状态;而我们的程序处于CLOSE_WAIT状态。
       Server <--- FIN <--- Client
这时Client发送FIN给Server,Client就置为LAST_ACK状态。
        Server ---> ACK ---> Client
Server回应了ACK,那么Client的套接字才会真正置为CLOSED状态。

我们的程序处于CLOSE_WAIT状态,而不是LAST_ACK状态,说明还没有发FIN给Server,那么可能是在关闭连接之前还有许多数据要发送或者其他事要做,导致没有发这个FIN packet。
原因知道了,那么为什么不发FIN包呢,难道会在关闭己方连接前有那么多事情要做吗?
还有一个问题,为什么有数千个连接都处于这个状态呢?难道那段时间内,服务器端总是主动拆除我们的连接吗?
不管怎么样,我们必须防止类似情况再度发生!
首先,我们要防止不断开辟新的端口,这可以通过设置SO_REUSEADDR套接字选项做到:
重用本地地址和端口
以前我总是一个端口不行,就换一个新的使用,所以导致让数千个端口进入CLOSE_WAIT状态。如果下次还发生这种尴尬状况,我希望加一个限定,只是当前这个端口处于CLOSE_WAIT状态!
在调用
sockConnected = socket(AF_INET, SOCK_STREAM, 0);
之后,我们要设置该套接字的选项来重用:
/// 允许重用本地地址和端口:
/// 这样的好处是,即使socket断了,调用前面的socket函数也不会占用另一个,而是始终就是一个端口
/// 这样防止socket始终连接不上,那么按照原来的做法,会不断地换端口。
int nREUSEADDR = 1;
setsockopt(sockConnected,
              SOL_SOCKET,
              SO_REUSEADDR,
              (const char*)&nREUSEADDR,
              sizeof(int));

教科书上是这么说的:这样,假如服务器关闭或者退出,造成本地地址和端口都处于TIME_WAIT状态,那么SO_REUSEADDR就显得非常有用。
也许我们无法避免被冻结在CLOSE_WAIT状态永远不出现,但起码可以保证不会占用新的端口。
其次,我们要设置SO_LINGER套接字选项:
从容关闭还是强行关闭?
LINGER是“拖延”的意思。
默认情况下(Win2k),SO_DONTLINGER套接字选项的是1;SO_LINGER选项是,linger为{l_onoff:0,l_linger:0}。
如果在发送数据的过程中(send()没有完成,还有数据没发送)而调用了closesocket(),以前我们一般采取的措施是“从容关闭”:
因为在退出服务或者每次重新建立socket之前,我都会先调用
/// 先将双向的通讯关闭
     shutdown(sockConnected, SD_BOTH);
     /// 安全起见,每次建立Socket连接前,先把这个旧连接关闭
closesocket(sockConnected);
我们这次要这么做:
设置SO_LINGER为零(亦即linger结构中的l_onoff域设为非零,但l_linger为0),便不用担心closesocket调用进入“锁定”状态(等待完成),不论是否有排队数据未发送或未被确认。这种关闭方式称为“强行关闭”,因为套接字的虚电路立即被复位,尚未发出的所有数据都会丢失。在远端的recv()调用都会失败,并返回WSAECONNRESET错误。
在connect成功建立连接之后设置该选项:
linger m_sLinger;
m_sLinger.l_onoff = 1; // (在closesocket()调用,但是还有数据没发送完毕的时候容许逗留)
m_sLinger.l_linger = 0; // (容许逗留的时间为0秒)
setsockopt(sockConnected,
         SOL_SOCKET,
         SO_LINGER,
         (const char*)&m_sLinger,
         sizeof(linger));

总结
也许我们避免不了CLOSE_WAIT状态冻结的再次出现,但我们会使影响降到最小,希望那个重用套接字选项能够使得下一次重新建立连接时可以把CLOSE_WAIT状态踢掉

TCP close_wait 状态的解释相关推荐

  1. 计算机端口 closewait,TCP端口状态说明ESTABLISHED、TIME_WAIT、 CLOSE_WAIT

    一. 首先说下tcp端口的几种状态: 1.LISTENING状态 FTP服务启动后首先处于侦听(LISTENING)状态. 2.ESTABLISHED状态 ESTABLISHED的意思是建立连接.表示 ...

  2. TCP连接大量CLOSE_WAIT状态问题排查

    CLOSE_WAIT产生原因 close_wait是被动关闭连接是形成的,根据TCP状态机,服务器端收到客户端发送的FIN,TCP协议栈会自动发送ACK,链接进入close_wait状态.但如果服务器 ...

  3. 解决Linux服务器中TCP的FIN_WAIT2,CLOSE_WAIT状态连接过多的问题

    问题现象 Linux系统服务器中FIN_WAIT2,CLOSE_WAIT状态的TCP链接过多,服务不能及时响应. 通过命令 netstat –ant|grep FIN_WAIT2|wc –l 查看连接 ...

  4. TCP 连接管理机制(二)——TCP四次挥手的TIME_WAIT、CLOSE_WAIT状态

    介绍三次握手的时候,着重了解的是三次握手过程中,应用层和传输层做了哪些工作:下面在了解四次挥手的时候,主要了解的是四次挥手的状态变化. 目录 一.四次挥手 1.第一次挥手 2.第二次挥手 3.第三次挥 ...

  5. qt程序使用tcp连接,客户端退出后,再次重连服务器,一直出现close_wait状态,且无法再连接上

    百度了tcp的各个状态,看到了 CLOSE_WAIT状态的原因与解决方法(转载留自己看)_编程小生的专栏-CSDN博客_close_wait 里面说的close_wait的现象,主要原因是某种情况下对 ...

  6. TCP连接状态详解及TIME_WAIT过多的解决方法

    TCP建立连接的三次握手过程,以及关闭连接的四次握手过程. TCP建立连接的三次握手过程,以及关闭连接的四次握手过程. 1.建立连接协议(三次握手) (1)客户端发送一个带SYN标志的TCP报文到服务 ...

  7. TCP的状态转换及生产问题实操

    前文介绍了TCP协议主要的流程,包括建立连接.传输数据和断开连接.如果大家认真阅读了附图,应该可以看到在各个流程中套接字的状态是在不断变化的,不同的状态标识了套集字所处的阶段. 如图1是TCP一个完整 ...

  8. TCP close_wait内幕

    最近调试时遇到一个tcp连接 一发交易server端就从es连接状态变成close_wait状态的问题. tcp连接需要三次握手,而被动关闭连接则是需要四次握手的,不能说单方面关闭连接就是成功关闭连接 ...

  9. 客户端产生CLOSE_WAIT状态的解决方案

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 现象 生 ...

最新文章

  1. 固定表头和首行_Excel一步制作斜线表头!还有这些高分Excel表头技巧,看完秒会...
  2. 初识C语言---(3)
  3. cics oracle xad_Cics安装与配置
  4. bagging 与boosting
  5. [蓝桥杯2017初赛]算式900+dfs,next_permutation
  6. 交换机的端口结构及端口类型
  7. 宽字符串忽略大小写比较的实现(原)
  8. android jni fork()子进程不运行_Android高级面试谈谈Zygote的理解
  9. 参加kaggle比赛
  10. Spring MVC对象转换说明
  11. python简明教程3.0_Python 简明教程 --- 0,前言
  12. PDF控件Spire.PDF 3.9.584发布 | 附下载
  13. 如何提高在外国网站下载软件或文件的速度
  14. SuperMemo UX 添加笔记 Ctrl+H
  15. 基于Tofino2的64X100GE高性能可编程交换机MX7636-64X
  16. Android 九宫格图片展示的实现
  17. Jetty 使用 以及HTML 和Js代码无法保存问题解决
  18. JAVA用一维数组生成福彩双色球中奖号码
  19. 实验6-cp –r系统命令的实现--源路径(目录)中的所有文件和子目录,以及子目录中的所有内容,全部拷贝到目标路径(目录)中--操作系统实验
  20. 波特词干算法(英文分词)

热门文章

  1. matlab中单独存图_Matlab中图片保存的四种方法
  2. 骄傲的代价_JAVA
  3. opencv 人脸检测
  4. Java 泛型中? super T和? extends T的区别
  5. Vue.js 自定义事件
  6. HTML Input 属性
  7. java提高篇(十二)-----代码块
  8. 一道面试题引发的对JavaScript类型转换的思考
  9. 使用强大的 Mockito 测试框架来测试你的代码
  10. 编程之美-1的数目方法整理