雅虎新闻|| BBC新闻|| CNN新闻|| 美元指数|| 中国期货指数|| 股票指数|| 黄金|| 外汇|| 英汉互译|| 昭放工具
163邮箱|| 126邮箱|| 新浪邮箱|| 企业邮箱|| 21cn邮箱|| tom邮箱|| 搜狐邮箱|| hotmail邮箱|| msn邮箱|| qq邮箱

用户登录

设为主页| 淘宝铺| 加入收藏|
您的IP:18.117.81.240您的操作系统:Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)
个人便签
知识库
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. 在发送连接请求后等待匹配的连接请求 */

  www.2cto.com  

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对连接中断的确认 */  www.2cto.com  

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报文要么完全响应完毕,要么被丢弃。建立第二个连接的时候,不 会混淆。  www.2cto.com  

为什么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 = 1

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_tw_recycle = 1

net.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,表示关闭。  www.2cto.com  

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   www.2cto.com  

KeepAliveTime,设置其值为300000(单位为毫秒,300000代表5分钟) 

TcpMaxDataRetransmissions,设置其值为5

Close_Wait引发的问题:

Close_Wait会占用一个连接,网络可用连接小。数量过多,可能会引起网络性能下降,并占用系统非换页内存。 尤其是在有连接池的情况下(比如HttpRequest)

会耗尽连接池的网络连接数,导致无法建立网络连接

 

REF: 

http://blog.zhuzhaoyuan.com/2009/03/a-word-on-time_wait-and-close_wait/ (这个讲解清楚)

http://kerry.blog.51cto.com/172631/105233

http://www.php-oa.com/2008/04/25/apachedekeepalivehetcpipdetime_wait.html

http://davidhew.blogbus.com/logs/48967567.html

http://blog.csdn.net/lllxy/archive/2007/09/10/1779866.aspx

http://haka.sharera.com/blog/BlogTopic/32309.htm

http://www.cppblog.com/prayer/archive/2009/06/15/87737.html

星期四, 08/07/2014 - 11:34 — 杨超