`

CLOSE_WAIT状态说明

阅读更多

CLOSE_WAIT出现的原因: 就是某一方在网络连接断开后,对等方没有检测到这个错误(对方断开)而没有调用 closesocket,导致了这个状态的出现;
 
断开连接的时候: 
当发起主动关闭的左边这方发送一个FIN过去后,右边被动关闭的这方要回应一个ACK,这个ACK是TCP回应的(同时TCP向上层应用程序提交一个ERROR,导致上面的SOCKET的send或者recv返回SOCKET_ERROR),而不是应用程序发送的,此时,被动关闭的一方就处于CLOSE_WAIT状态了。如果此时被动关闭的这一方不再继续调用closesocket,那么他就不会发送接下来的FIN,导致自己老是处于CLOSE_WAIT。只有被动关闭的这一方调用了closesocket,才会发送一个FIN给主动关闭的这一方,同时也使得自己的状态变迁为LAST_ACK,待接收到主动关闭方发送的ACK后,才会将SOCKET置为CLOSED。 
检测到SOCKET_ORROR 则主动调用closesocket() 关闭套接字; 
***************************************************************
首先我们知道,如果我们的Client程序处于CLOSE_WAIT状态的话,说明套接字是被动关闭的!
因为如果是Server端主动断掉当前连接的话,那么双方关闭这个TCP连接共需要四个packet
       Server ---> FIN ---> Client
       Server <--- ACK <--- Client
    时候Server端处于FIN_WAIT_2状态;而我们的程序处于CLOSE_WAIT状态。
       Server <--- FIN <--- Client
Client发送FINServerClient就置为LAST_ACK态。
       Server ---> ACK ---> Client
Server回应了ACK,那么Client的套接字才会真正置为CLOSED状态。
image

我们的程序处于CLOSE_WAIT状态,而不是LAST_ACK,说明还没有发FINServer,那么可能是在关闭连接之前还有许多数据要发送或者其他事要做,导致没有发这个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套接字选项:(相关介绍可参考:SO_LINGER 选项设置)
从容关闭还是强行关闭?
LINGER是“拖延”的意思。
默认情况下(Win2k)SO_DONTLINGER套接字选项的是1SO_LINGER选项是,linger{l_onoff0l_linger0}
如果在发送数据的过程中(send()没有完成,还有数据没发送)而调用了closesocket(),以前我们一般采取的措施是“从容关闭”:
因为在退出服务或者每次重新建立socket之前,我都会先调用
/// 先将双向的通讯关闭
shutdown(sockConnected, SD_BOTH);
/// 安全起见,每次建立Socket连接前,先把这个旧连接关闭
closesocket(sockConnected);
我们这次要这么做:
设置SO_LINGER为零(亦即linger结构中的l_onoff域设为非零,但l_linger0,便不用担心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_SYNC基础

    服务器程序 APACHE 处于 CLOSE_WAIT 状态,说明套接字是被动关闭的!如果是客户端主动断开连接,服务器端的连接会处在“挂起”状态。 TCP SYNC 基础知识非常重要,对于程序员和网络管理员来说都是必备知识。在编写...

    tcp连接状态详解 描述了tcp协议常用的命令

    最后,被动关闭的一方会由 CLOSE_WAIT 状态转移到 LAST_ACK 状态,发送 FIN 给对方,同时在接收到 ACK 时进入 CLOSED 状态。 TIME_WAIT 状态是 TCP 连接状态中最复杂的状态。它可以由多个状态转移到达,包括 FIN_...

    tcp状态解析和windowsio说明

    10. **CLOSE_WAIT**: 被动关闭的一方(通常为服务器)收到对方的FIN包后,发送ACK并进入CLOSE_WAIT状态。在此状态下,服务器等待应用程序通知关闭连接。 11. **LAST_ACK**: 如果在CLOSE_WAIT状态下,服务器也发送了...

    linux 下tcp参数优化

    在这个过程中,Server 程序处于 CLOSE_WAIT 状态,而不是 LAST_ACK 状态,说明还没有发 FIN 给 Client,可能是在关闭连接之前还有许多数据要发送或者其他事要做,导致没有发这个 FIN packet。 proc/sys/net/ipv4/ ...

    httpclient-closewait-samples:一个简单的示例,说明如何使用Apache HttpCommons Client避免在客户端进行CLOSE_WAIT连接

    因此,您将使那些CLOSE_WAIT连接处于挂起状态并声称已关闭。 要说明此行为,请查看此存储库中的示例。 简而言之,我们正在做的是: 在整个生命周期中创建一个连接管理器和一个HttpClient连接 创建15个线程以执行...

    f5 会话处理流程描述(参数说明)及q&a_0120资料.pdf

    二、连接状态说明 在 F5 会话处理流程中,连接状态是非常重要的一部分。下面是连接状态的详细描述: * CLOSED:表示初始状态。 * LISTEN:表示服务器端的某个 SOCKET 处于监听状态,可以接受连接了。 * SYN_RCVD:...

    tcpip4次握手形象版

    此时服务端状态变为`CLOSE_WAIT`,表明它已经收到了客户端的断开请求,但自身还没有准备好关闭连接。 **三、客户端发送第二次挥手** 客户端在收到服务端发来的确认后,状态由`FIN_WAIT_1`变为`FIN_WAIT_2`,表示...

    TCP-IP详解卷二:实现\029.PDF

    在TIME_WAIT状态,接收到ACK会重新启动2MSL定时器。图29-1展示了ACK处理的整体流程。 29.3章节详细说明了在SYN_RECEIVED状态下如何处理接收到的ACK报文段。如果ACK确认了已发送的SYN,并且在有效范围内,TCP会进入...

    tcphist aa

    TCP连接有多种状态,如SYN_SENT(同步已发送)、ESTABLISHED(已建立)、FIN_WAIT_1、FIN_WAIT_2、CLOSE_WAIT、CLOSING、LAST_ACK、TIME_WAIT等,每个状态都代表了连接的不同阶段。`tcphist aa`工具能够帮助用户监控...

    滴滴出行2016研发工程师笔试题及答案(四).pdf

    - TCP连接的主动关闭方(发送FIN的一方)不会进入CLOSE_WAIT状态,而是会依次经历FIN_WAIT1、FIN_WAIT2和TIME_WAIT状态。 4. **排序算法**: - 在最坏情况下,归并排序保持O(n log n)的时间复杂度,而冒泡排序、...

    Spring Boot假死诊断实战记录

    CLOSE_WAIT状态是TCP连接中的一个状态,表示服务器端的连接已经关闭,而客户端还没有关闭连接。这可能是由于服务器端的资源问题或网络问题引起的。在这个案例中,作者怀疑是GC导致了STW(Stop The World),但实际上...

    sem.rar_in_linux semaphore

    在Linux中,信号量主要通过两个系统调用来操作:`sem_open()`、`sem_close()`、`sem_unlink()`、`sem_post()`和`sem_wait()`。`sem_open()`用于创建或打开一个信号量,`sem_close()`关闭信号量,`sem_unlink()`删除...

    TCP/IP协议说明

    TCP的状态转移详解在“TCP状态转移详解.mp4”中会有详述,从CLOSED到ESTABLISHED,再到FIN_WAIT、CLOSE_WAIT、LAST_ACK等状态,每个状态代表了连接的不同阶段,理解这些状态转换对于排查网络问题和优化TCP连接至关...

    挖掘鸡,蝙蝠侠

    挖掘鸡 v7.1:改掉close_wait状态。忽略扫描域名无效等问题。是否更新。23说明:30 2009-10-5 挖掘鸡 v7.0:进一步增大扫描范围。改进扫描算法和效率;这个软件这个软件这个软件工具你本人关键词联想。非常肯定超长...

    sem_fun.rar_Fun_ Fun_ Fun_sem lin

    `sem_getvalue`函数用于获取信号量的当前值,这对于监控系统状态和调试非常有用。 5. **删除信号量(sem_close和sem_unlink)**: `sem_close`关闭一个已打开的信号量,而`sem_unlink`则删除一个命名信号量,使其...

    rabbitmq的接口函数说明,api参数使用说明

    **声明**:`void amqp_close_connection(amqp_connection_state_t state, int reply_code, char const *reply_text);` 此函数用于关闭连接。 **参数说明**: - `state`: 当前的RabbitMQ连接状态。 - `reply_code`...

    信息安全实习

    - FIN_WAIT_1、FIN_WAIT_2、TIME_WAIT、CLOSE_WAIT、LAST_ACK、CLOSED:分别描述了主动关闭和被动关闭过程中不同的状态。 5. TCP报文结构 文档还涉及了TCP报文的结构,这是理解TCP协议工作的基础。TCP报文段包括...

    epoll 手册 man 翻译 使用说明

    - 当 read 或 write 操作返回 `EAGAIN` 时,表示已经到达非阻塞状态下的数据边界,这时应该等待下一个事件。 - 即使使用 EPOLLONESHOT 标志,也需要确保文件描述符是非阻塞的,因为这样做可以确保在处理完一个事件后...

    挖掘鸡最新版

    挖掘鸡 v7.1:修改close_wait状态,忽略扫描域名无效等问题。是否更新。23:30 2009-10-5 挖掘鸡 v7.0:进一步增大扫描范围,改进扫描算法和效率;自动关键词联想,支持超长时间扫描等。建议更新。20:46 2009-7-30 ...

Global site tag (gtag.js) - Google Analytics