`
liuguxing
  • 浏览: 95112 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

TCP的状态,兼谈Close_Wait和Time_Wait的状态

 
阅读更多
TCP的状态,兼谈Close_Wait和Time_Wait的状态

一TCP的状态:
1)、LISTEN:首先服务端需要打开一个socket进行监听,状态为LISTEN. /* The socket is listening for incoming connections. 侦听来自远方TCP端口的连接请求 */
2)、SYN_SENT:客户端通过应用程序调用connect进行active open.于是客户端tcp发送一个SYN以请求建立一个连接.之后状态置为SYN_SENT. /*The socket is actively attempting to establish a connection. 在发送连接请求后等待匹配的连接请求 */
3)、SYN_RECV:服务端应发出ACK确认客户端的SYN,同时自己向客户端发送一个SYN.之后状态置为SYN_RECV /* A connection request has been received from the network. 在收到和发送一个连接请求后等待对连接请求的确认 */
4)、ESTABLISHED: 代表一个打开的连接,双方可以进行或已经在数据交互了。/* The socket has an established connection. 代表一个打开的连接,数据可以传送给用户 */
5)、FIN_WAIT1:主动关闭(active close)端应用程序调用close,于是其TCP发出FIN请求主动关闭连接,之后进入FIN_WAIT1状态./* The socket is closed, and the connection is shutting down. 等待远程TCP的连接中断请求,或先前的连接中断请求的确认 */
6)、CLOSE_WAIT:被动关闭(passive close)端TCP接到FIN后,就发出ACK以回应FIN请求(它的接收也作为文件结束符传递给上层应用程序),并进入CLOSE_WAIT. /* The remote end has shut down, waiting for the socket to close. 等待从本地用户发来的连接中断请求 */
7)、FIN_WAIT2:主动关闭端接到ACK后,就进入了FIN-WAIT-2 ./* Connection is closed, and the socket is waiting for a shutdown from the remote end. 从远程TCP等待连接中断请求 */
8)、LAST_ACK:被动关闭端一段时间后,接收到文件结束符的应用程序将调用CLOSE关闭连接。这导致它的TCP也发送一个 FIN,等待对方的ACK.就进入了LAST-ACK . /* The remote end has shut down, and the socket is closed. Waiting for acknowledgement. 等待原来发向远程TCP的连接中断请求的确认 */
9)、TIME_WAIT:在主动关闭端接收到FIN后,TCP就发送ACK包,并进入TIME-WAIT状态。/* The socket is waiting after close to handle packets still in the network.等待足够的时间以确保远程TCP接收到连接中断请求的确认 */
10)、CLOSING: 比较少见./* Both sockets are shut down but we still don't have all our data sent. 等待远程TCP对连接中断的确认 */
11)、CLOSED: 被动关闭端在接受到ACK包后,就进入了closed的状态。连接结束./* The socket is not being used. 没有任何连接状态 */
TCP状态图:


二TCP正常关闭连接的状态变化根据《TCP/IP详解》中的TCP的建立和终止中有关"TCP的终止"的讲解TCP的终止通过双方的四次握手实现。发起终止的一方执行主动关闭,响应的另一方执行被动关闭。1. 发起方更改状态为FIN_WAIT_1,关闭应用程序进程,发出一个TCP的FIN段;2. 接收方收到FIN段,返回一个带确认序号的ACK,同时向自己对应的进程发送一个文件结束符EOF,同时更改状态为CLOSE_WAIT,发起方接到ACK后状态更改为FIN_WAIT_2;3. 接收方关闭应用程序进程,更改状态为LAST_ACK,并向对方发出一个TCP的FIN段;4. 发起方接到FIN后状态更改为TIME_WAIT,并发出这个FIN的ACK确认。ACK发送成功后(2MSL内)双方TCP状态变为CLOSED。
三Time_Wait状态解释
根据TCP协议,主动发起关闭的一方,会进入TIME_WAIT状态(TCP实现必须可靠地终止连接的两个方向(全双工关闭)),持续2*MSL(Max Segment Lifetime),缺省为240秒.TIME_WAIT的等待时间为2MSL,即最大段生存时间.如果 TIME_WAIT 状态保持时间不足够长(比如小于2MSL),第一个连接就正常终止了。第二个拥有相同相关五元组的连接出现(因为连接终止前发起的一方可能需要重发 ACK,所以停留在该状态的时间必须为MSL的2倍。),而第一个连接的重复报文到达,干扰了第二个连接。TCP实现必须防止某个连接的重复报文在连接终 止后出现,所以让TIME_WAIT态保持时间足够长(2MSL),连接相应方向上的TCP报文要么完全响应完毕,要么被丢弃。建立第二个连接的时候,不 会混淆。为什么TIME_WAIT 状态 停留2MSL(max segment lifetime)时间也就是TCP/IP设计者本来是这么设计的主要有两个原因1。防止上一次连接中的包,迷路后重新出现,影响新连接(经过2MSL,上一次连接中所有的重复包都会消失)2。可靠的关闭TCP连接在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。修改Time_Wait参数的方法 Windows下在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters,添加名为TcpTimedWaitDelay的DWORD键,设置为60,以缩短TIME_WAIT的等待时间 Linux下修改:vi /etc/sysctl.conf编辑文件,加入以下内容:net.ipv4.tcp_syncookies = 1net.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_tw_recycle = 1net.ipv4.tcp_fin_timeout = 30 然后执行 /sbin/sysctl -p 让参数生效。 net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间
Time_Wait引发的问题:Timewait是正常的现象,但是比较多的时候(比如3000)则可能引发CPU利用率高需要有效降低
四   Close_Wait状态解释
CLOSE_WAIT状态的生成原因通过TCP的状态图我们可以看出只有被动关闭的一端才有CLOSE_WAIT状态,当收到Fin并发送了Ack后服务器状态就变成了CLOSE_WAIT状态,如果我们的服务器一直处于CLOSE_WAIT状态的话,说明套接字是被动关闭的!,并且没有发送Fin信令,原因往往是没有调用TCP的CloseSocket。
解决CLOSE_WAIT的方法:1 一般原因都是TCP连接没有调用关闭方法。需要应用来处理网络链接关闭。2 对于Web请求出现这个原因,经常是因为Response的BodyStream没有调用Close.比如Widnows下:使用HttpWebRequest 一定要保证GetRequestStream和GetResponse对象关闭,否则容易造成连接处于CLOSE_WAIT状态3 TCP的KeepLive功能,可以让操作系统替我们自动清理掉CLOSE_WAIT的连接。但是KeepLive在Windows操作系统下默认是7200秒,也就是2个小时才清理一次。往往满足不了要求。可以调小该数值。Windows下的调整方法为HKEY_LOCAL_MACHINE\CurrentControlSet\Services\Tcpip\Parameters下的以下三个参数: KeepAliveInterval,设置其值为1000 KeepAliveTime,设置其值为300000(单位为毫秒,300000代表5分钟) TcpMaxDataRetransmissions,设置其值为5
Close_Wait引发的问题:Close_Wait会占用一个连接,网络可用连接小。数量过多,可能会引起网络性能下降,并占用系统非换页内存。 尤其是在有连接池的情况下(比如HttpRequest)会耗尽连接池的网络连接数,导致无法建立网络连接五   TCP的KeepAlive
在一个正常的TCP连接上,当我们用无限等待的方式调用下面的recv或send的时候:
    ret=recv(s,&buf[idx],nLeft,flags);或
    ret=send(s,&buf[idx],nLeft,flags);

如果TCP连接被对方正常关闭,也就是说,对方是正确地调用了closesocket(s)或者shutdown(s)的话,那么上面的recv或send调用就能马上返回,并且报错。这是由于closesocket()或者shutdown()有个正常的关闭过程,会告诉对方“TCP连接已经关闭,你不需要再发送或者接受消息了”。但是,如果是网线突然被拔掉,TCP连接的任何一端的机器突然断电或重启动,那么这时候正在执行recv或send操作的一方就会因为没有任何连接中断的通知而一直等待下去,也就是会被长时间卡住。这种情形解决的办法是启动TCP编程里的keepAlive机制。
    #include “mstcpip.h”
    tcp_keepalive inKeepAlive = {0};    unsigned long ulInLen = sizeof(tcp_keepalive);    tcp_keepalive utKeepAlive = {0};    unsigned long ulOutLen = sizeof(tcp_keepalive);    unsigned long ulBytesReturn = 0;
    int ret;
    inKeepAlive.onoff=1;    inKeepAlive.keepaliveinterval=5000; //单位为毫秒    inKeepAlive.keepalivetime=1000;     //单位为毫秒
    ret=WSAIoctl(s, SIO_KEEPALIVE_VALS, (LPVOID)&inKeepAlive, ulInLen,  (LPVOID)&outKeepAlive, ulOutLen, &ulBytesReturn, NULL, NULL);

    此处的keepalivetime表示的是TCP连接处于畅通时候的探测频率,一旦探测包没有返回,就以keepaliveinterval的频率发送,经过若干次的重试,如果探测包都没有返回,那么就得出结论:TCP连接已经断开,于是上面的recv或send调用也就能马上返回,不会无限制地卡住了。

图 1 Wireshark Keep-Alive抓包

上图是对上面文字的说明。被选中的包(第32行)之前,TCP处于畅通状态,KeepAlive是以1000毫秒(keepalivetime的值)的频率发送探测包,在发送到第32个探测包的时候,探测包没有返回,于是就以5000毫秒(keepalivetime的值)的频率发送探测包,重发几次后,探测包都没有返回, 于是就得出结论:此TCP连接已经断开了!

对于Win2K/XP/2003,可以从下面的注册表项找到影响整个系统所有连接的keepalive参数:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
“KeepAliveTime”=dword:006ddd00“KeepAliveInterval”=dword:000003e8“MaxDataRetries”=”5″

对于实用程序来说,2小时的空闲时间太长。因此,我们需要手工开启Keepalive功能并设置合理的Keepalive参数。在XP和WIN2003系统上,可以针对单独的socket来设置,但是在windows 2000,不能单独设置,如果设置,那么影响是整个系统的所有socket。

REF: http://blog.zhuzhaoyuan.com/2009/03/a-word-on-time_wait-and-close_wait/ (这个讲解清楚)http://kerry.blog.51cto.com/172631/105233http://www.php-oa.com/2008/04/25/apachedekeepalivehetcpipdetime_wait.htmlhttp://davidhew.blogbus.com/logs/48967567.htmlhttp://blog.csdn.net/lllxy/archive/2007/09/10/1779866.aspxhttp://haka.sharera.com/blog/BlogTopic/32309.htmhttp://www.cppblog.com/prayer/archive/2009/06/15/87737.html
分享到:
评论

相关推荐

    TCP状态迁移,CLOSE_WAIT & FIN_WAIT2 的问题解决

    在 TCP 连接中,客户端和服务器端都可以处于不同的状态,例如 ESTABLISHED、CLOSE_WAIT、FIN_WAIT_1、FIN_WAIT_2、TIME_WAIT 等 trạng thái。 CLOSE_WAIT 状态是 TCP 连接中的一种状态,它表示服务器端已经收到了...

    CLOSE_WAIT网络连接无法释放问题解决

    使用netstat -na命令可以查看当前的TCP连接状态,包括LISTEN、ESTABLISHED、TIME_WAIT等状态。在这个例子中,使用netstat -na命令可以发现服务器端的连接状态为CLOSE_WAIT,这就表明服务器端的连接尚未释放。 通过...

    tcp连接出现close_wait状态?_tcp_close_

    TCP连接有多种状态,包括LISTEN、SYN_SENT、SYN_RECEIVED、ESTABLISHED、CLOSE_WAIT、FIN_WAIT_1、FIN_WAIT_2、TIME_WAIT等。每个状态都代表了连接的不同生命周期阶段。Close_Wait是服务器端接收到客户端的FIN( ...

    close_wait_0306 close_wait_0306 close_wait_0306 close_wait_0306

    文件"close_wait_0306.chm"和"close_wait_0306"可能是关于这个问题的文档或日志文件,它们可能包含了更详细的错误信息、堆栈跟踪或连接状态的历史记录。CHM文件是Microsoft的帮助文件格式,通常包含软件的文档或技术...

    CLOSE_WAIT错误详解

    在TCP/IP协议栈中,CLOSE_WAIT是一个非常关键的连接状态,它涉及到客户端和服务器之间的通信。这个状态在处理网络连接时可能出现的问题时尤其重要。本文将深入探讨CLOSE_WAIT错误的含义、原因以及如何解决。 首先,...

    系统调优,你所不知道的TIME_WAIT和CLOSE_WAIT1

    系统调优时,理解和处理TIME_WAIT和CLOSE_WAIT状态是关键。TIME_WAIT是为了保证TCP的可靠性,但过多的TIME_WAIT会占用资源。CLOSE_WAIT则可能指示应用程序或系统的问题。解决这些问题需要深入理解TCP连接生命周期,...

    Close_Wait问题相关资料

    在TCP/IP协议栈中,"Close_Wait"是一种连接状态,表示一个方向的连接已经关闭,而另一个方向仍然保持开放,等待应用层关闭。当服务器接收到客户端的FIN(结束)标志,它会进入Close_Wait状态,表示服务器已经接收到...

    TIME_WAIT.rar_C-means_linux 网络状态_linux c wait_tcp_unix 网络编程

    在处理TCP连接时,需要特别关注close()函数的使用,因为它可能直接影响到TIME_WAIT状态的处理。 `c-means`可能是指一种基于C语言的聚类算法,虽然在这个上下文中没有直接关联,但如果你正在学习C语言编程,并试图将...

    TCP_SYNC基础

    如果对方在第三次握手的时候出问题,例如发 FIN 包的时候,不知道什么原因丢了这个包,客户端会一直处在 FIN_WAIT_2 状态,服务器端则处在 CLOSE_WAIT 状态。如果这种情况持续很长时间,系统可能会崩溃。 问题分析 ...

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

    它可以由多个状态转移到达,包括 FIN_WAIT_2、CLOSING 和 FIN_WAIT_1 状态。TIME_WAIT 状态的存在是为了确保 TCP 连接的可靠终止和允许老的重复分节在网络中消逝。 了解 TCP 连接状态是非常重要的,因为它可以帮助...

    tcp状态解析和windowsio说明

    主动关闭可能会经过FIN_WAIT_1、FIN_WAIT_2、TIME_WAIT状态,而被动关闭则经历CLOSE_WAIT、LAST_ACK状态。在处理TIME_WAIT状态时,需要注意避免端口冲突,可以使用SO_REUSEADDR选项来允许立即重用套接字地址,或者...

    tomcat-timewait-closewait.zip

    标题 "tomcat-timewait-closewait.zip" 暗示了这个压缩包可能包含与Tomcat服务器在处理TCP连接时遇到的“Time_wait”和“Close_wait”状态相关的问题和解决方案。这两个术语是TCP/IP协议栈中的关键概念,尤其在高...

    Netstat命令详解如何关闭TIME_WAIT连接如何查看nginx的访问流量[归类].pdf

    5. FIN_WAIT1:主动关闭(active close)端应用程序调用 close,于是其 TCP发出 FIN 请求主动关闭连接,之后进入 FIN_WAIT1 状态。 6. CLOSE_WAIT:被动关闭(passive close)端 TCP 接到 FIN。 7. FIN_WAIT2:主动...

    TCP状态变迁图-描述各个状态之间变迁

    在极少数情况下,双方可能同时尝试关闭连接,导致双方都处于FIN_WAIT_1和LAST_ACK状态。这种情况下,双方都会进入短暂的CLOSING状态,等待对方的ACK。 12. **CLOSED**: 无论是主动关闭连接的一方还是被动关闭的...

    TCP状态机详细描述

    - 当主动关闭方发送FIN报文段后,状态变为`FIN_WAIT_1`。 - 主动关闭方接收到ACK报文段后,状态变为`FIN_WAIT_2`。 - 被动关闭方接收到FIN报文段并发送ACK报文段后,状态变为`CLOSE_WAIT`。 - 被动关闭方发送FIN报文...

    TCP_CloseWaitProblem

    在内核级别,向应用程序发出关闭请求,并且CLOSE_WAIT的状态等待,并且连接保持超时。 使用命令netstat -p tcp -n | grep CLOSE_WAIT进行检查,如下所示。 tcp4 0 0 127.0.0.1.50937 127.0.0.1.8383 CLOSE_WAIT ...

    TCP有限状态机

    客户端发送FIN后进入FIN_WAIT_1状态,接收到服务器ACK后进入FIN_WAIT_2状态,等待服务器发送FIN请求。 - **CLOSE_WAIT**:当服务器接收到客户端发送的FIN请求后,发送ACK确认,并进入此状态。这表明服务器已经准备好...

Global site tag (gtag.js) - Google Analytics