查看: 3404|回复: 1

TCP状态变迁

[复制链接]
发表于 2009-3-11 20:46:06 | 显示全部楼层 |阅读模式
TCP状态ITPUB  起初每个socket都是CLOSED状态,当客户端初使化一个连接,他发送一个SYN包到服务器,客户端进入SYN_SENT状态。
;DT%}-aE)LO6ZH0服务器接收到SYN包,反馈一个SYN-ACK包,客户端接收后返馈一个ACK包客户端变成ESTABLISHED状态,如果长时间没收到SYN-ACK包,客户端超时进入CLOSED状态。ITPUB个人空间9b/D&I0TMA@:I%P(f
当服务器绑定并监听某一端口时,socket的状态是LISTEN,当客户企图建立连接时,服务器收到一个SYN包,并反馈SYN-ACK包。服务器状态变成SYN_RCVD,当客户端发送一个ACK包时,服务器socket变成ESTABLISHED状态。
+R;W9{,R*U%p0当一个程序在ESTABLISHED状态时有两种图径关闭它, 第一是主动关闭,第二是被动关闭。ITPUB个人空间%r#U"~v.U M9G
如果你要主动关闭的话,发送一个FIN包。当你的程序closesocket或者shutdown(标记),你的程序发 送一个FIN包到peer,你的socket变成FIN_WAIT_1状态。peer反馈一个ACK包,你的socket进入FIN_WAIT_2状态。 如果peer也在关闭连接,那么它将发送一个FIN包到你的电脑,你反馈一个ACK包,并转成TIME_WAIT状态。TIME_WAIT状态又号2MSL等待状态。MSL意思是最大段生命周期(Maximum Segment Lifetime)表明一个包存在于网络上到被丢弃之间的时间。每个IP包有一个TTL(time_to_live),当它减到0时则包被丢弃。每个路由 器使TTL减一并且传送该包。当一个程序进入TIME_WAIT状态时,他有2个MSL的时间,这个充许TCP重发最后的ACK,万一最后的ACK丢失 了,使得FIN被重新传输。在2MSL等待状态完成后,socket进入CLOSED状态。ITPUB个人空间'jQm+fD s4p2c
被动关闭:当程序收到一个FIN包从peer,并 反馈一个ACK包,于是程序的socket转入CLOSE_WAIT状态。因为peer已经关闭了,所以不能发任何消息了。但程序还可以。要关闭连接,程 序自已发送给自已FIN,使程序的TCP socket状态变成LAST_ACK状态,当程序从peer收到ACK包时,程序进入CLOSED状态。
ossm6_3}0
oZ6P^l_m0TCP终止连接采用的是四次握手,如下图。ITPUB个人空间q'I0PC"xdB
FIN_WAIT_1:client发出fin以后,状态更新为fin_wait_1,server接收到来自client的fin以后状态也更改为fin_wait_1,立刻发送ack,ITPUB个人空间H#`w(D"D WIC'X
产生FIN_WAIT_2的实质是只完成了一次fin-ack的过程以后,client一直在等待来自server的第二次fin,但由于对端负荷过重,或者连接异常终止,导致对端无法发送FIN. 官方的说法是:Socket closed, waiting for shutdown from remote.ITPUB个人空间0V4C@;b1\da HIP
ITPUB个人空间"p] G9e9}0Bc-\i
Client                                                                               ServerITPUB个人空间F,e [P&Y$|g d
    1 ----------------------------FIN------------------------------> ITPUB个人空间zB9mQ z%l k w6\3I
FIN_WAIT_1                                                                 FIN_WAIT_1
re"W#A ~Q0F\&^ur:SU0    2 <--------------------------ACK-------------------------------
F)x cb%x0Q0 FIN_WAIT_2
$lw*{%{(T&` vKcS6OUv0    3 <--------------------------FIN--------------------------------
NHNQ-W W0    4 ----------------------------ACK------------------------------>
7Z ?-f_%Ue0TIME_WAIT

Impact:
-E8FY_{K%Y%nt~0If too many FIN_WAIT_2 sessions build up, it can fill up the space allocated for storing connection information and crash the Kernel.
j`1j\.j| zb0ITPUB个人空间7X;G3Y+G!sEY tB1{
Resolution or workaround:ITPUB个人空间5G\ \"jivG4}!_
The right way to handle this problem is for the TCP/IP stack to have a fin_wait2 timer that will shutdown sockets stuck in fin_wait2 state.

How long those FIN_WAIT_2 sockets stay in that state will depend on the "tcp_fin_wait_2_timeout" tcpip parameter.By default, HP will keep those FIN_WAIT_2 sockets around forever.To find out what your value is currently set to, issue :
%G;dg#k H9Dh2|K0#ndd -get /dev/tcp tcp_fin_wait_2_timeout

And to change this value to, say 1 hour, issue :ITPUB个人空间F ~$q U+n"}R
#ndd -set /dev/tcp tcp_fin_wait_2_timeout 3600000

Changing the parameter using the above ndd command will take effect immediately but that change will be lost when the system is rebooted. To make this change permanently, you need to edit the/etc/rc.config.d/nddconffile. By setting the "tcp_fin_wait_2_timeout" to 1 hour, the FIN_WAIT_2 sockets will be closed after 1 hour.

The FIN_WAIT_2 timer must be used with caution because when TCP is in the FIN_WAIT_2 state the remote is still allowed to send data. In addition, if the remote TCP would terminate normally (it is not hung nor terminating abnormally) and the connection is closed because of the FIN_WAIT_2 timer, the connection may be closed prematurely.

Data may be lost if the remote sends a window update or FIN after the local TCP has closed the connection. In this situation, the local TCP will send a RESET. According to the TCP protocol specification, the remote TCP should flush its receive queue when it receives the RESET. This may cause data to be lost.
回复

使用道具 举报

 楼主| 发表于 2009-3-11 20:46:30 | 显示全部楼层
7月6日
TCP状态迁移
大家对netstat -a命令很熟悉吧,但是,你有没有注意到STATE一栏呢,基本上显示着established,time_wait,close_wait等,这些到底是什么意思呢,在这篇文章,我将会详细的阐述。
   大家很明白TCP初始化连接三次握手吧:发SYN包,然后返回SYN/ACK包,再发ACK包,连接正式建立。但是这里有点出入,当请求者收到SYS/ACK包后,就开始建立连接了,而被请求者第三次握手结束后才建立连接。但是大家明白关闭连接的工作原理吗?关闭连接要四次握手:发FIN包,ACK包,FIN包,ACK包,四次握手!!为什么呢,因为TCP连接是全双工,我关了你的连接,并不等于你关了我的连接。
   客户端TCP状态迁移:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
   服务器TCP状态迁移:
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
当客户端开始连接时,服务器还处于LISTENING,客户端发一个SYN包后,他就处于SYN_SENT状态,服务器就处于SYS收到状态,然后互相确认进入连接状态ESTABLISHED.
当客户端请求关闭连接时,客户端发送一个FIN包后,客户端就进入FIN_WAIT_1状态,等待对方的确认包,服务器发送一个ACK包给客户,客户端收到ACK包后结束FIN_WAIT_1状态,进入FIN_WAIT_2状态,等待服务器发过来的关闭请求,服务器发一个FIN包后,进入CLOSE_WAIT状态,当客户端收到服务器的FIN包,FIN_WAIT_2状态就结束,然后给服务器端的FIN包给以一个确认包,客户端这时进入TIME_WAIT,当服务器收到确认包后,CLOSE_WAIT状态结束了,这时候服务器端真正的关闭了连接.但是客户端还在TIME_WAIT状态下,什么时候结束呢.我在这里再讲到一个新名词:2MSL等待状态,其实TIME_WAIT就是2MSL等待状态,为什么要设置这个状态,原因是有足够的时间让ACK包到达服务器端,如果服务器端没收到ACK包,超时了,然后重新发一个FIN包,直到服务器收到ACK包,TIME_WAIT状态等待时间是在TCP重新启动后不连接任何请求的两倍.
   大家有没有发现一个问题:如果对方在第三次握手的时候出问题,如发FIN包的时候,不知道什么原因丢了这个包,然而这边一直处在FIN_WAIT_2状态,而且TCP/IP并没有设置这个状态的过期时间,那他一直会保留这个状态下去,越来越多的FIN_WAIT_2状态会导致系统崩溃.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | CSNA会员注册

本版积分规则

快速回复 返回顶部 返回列表