一、TCP状态转换
-
端口一开始都是关闭状态
-
服务器调用accept()函数会把端口从
CLOSTED
变为LISTEN
状态 -
客户端调用connect()函数发送SYN报文后,就进入了
SYN_SEND
状态 -
服务器收到ACK报文会变成
ESTABLISHED
状态,然后就会产生新的套接字(处于数据可传输状态
与客户端的套接字进行数据传输),旧的套接字会从ESTABLISHED数据可传输状态
回到LISTEN监听状态
-
客户端调用close()函数发送FIN报文,也会
关闭掉客户端的套接字
,进入FIN_WAIT_1
状态,当客户端收到服务器回应的ACK报文后,就会从FIN_WAIT_1
状态变回FIN_WAIT_2
状态 -
服务器收到处于
FIN_WAIT1
客户端发送过来的FIN报文后,会变成CLOSE_WAIT
状态 -
然后,服务器端也调用close()函数,就会从
CLOSE_WAIT
状态转换为LAST_ACK
状态,同时发送FIN报文给客户端,客户端就就会变成TIME_WAIT
状态,然后回复ACK给服务器,那么服务器就会变成CLOSED
状态
被动方关闭的一端更早地进入
CLOSED状态
主动方关闭的一端会进入TIME_WAIT状态
,等一段时间后才能转化为CLOSED状态
。
二、观察每个状态
2.1 套接字处于LISTEN状态
- 注意:是accept()函数的调用让服务器的状态从
CLOSED
变成LISTEN
状态。调用listen()
函数只是让服务器具备监听能力
。 - SYN_SENT和SYN_RECV状态是捕捉不到的,因为很快(
ACK
是自动回复的,所以状态转换
很快)。但是ESTABLISHED状态是可以的——
当我们先只打开服务器
的时候,我们就进入了LISTEN状态:
LISTEN状态
紧接着,当我们再打开客户端以后,就进入了ESTABLISHED状态:
ESTABLISHED状态
- 同理,因为
ACK是协议栈自动回复
的,所以FIN_WAIT1
这个状态是捕捉不到的
主动调用close()的函数的一端就会处于
FIN_WAIT2状态
,被动关闭的就是处于CLOSED_WAIT
状态
2.2 FIN_WAIT_2状态和CLOES_WAIT状态
- 客户端先关闭套接字,但是服务器并不关闭套接字:
图示结果
CLOSE_WAIT状态有一个超时时间,过一会儿就会自动消失
2.3 TIME_WAIT状态
- 2MSL
为什么不直接关闭掉,而是要等
2MSL
?
出现了大量的
CLOSE_WAIT状态
的原因?
服务器端的代码有bug,忘记调用close()
函数关闭套接字了
客户端处于
TIME_WAIT状态
是无所谓的,因为端口可以临时分配,但是服务器端如果是TIME_WAIT状态
就会导致端口不被释放,一直在2MSL中处于被占用状态。
网友评论