TCP状态迁移,CLOSE 您所在的位置:网站首页 tcp的close_wait TCP状态迁移,CLOSE

TCP状态迁移,CLOSE

2024-07-12 08:38| 来源: 网络整理| 查看: 265

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状态会导致系统崩溃.

上面我碰到的这个问题主要因为TCP的结束流程未走完,造成连接未释放。现设客户端主动断开连接,流程如下

如上图所示, Client                            消息                                    Server

         close() ------ FIN -------> FIN_WAIT1                                                         CLOSE_WAIT FIN ---> Server

Client RHEL3:2175 (CLOSE_WAIT) oracle    22725 oracle9i    9u IPv4 18621578       TCP RHEL3:6800->RHEL3:2176 (CLOSE_WAIT) oracle    22726 oracle9i    3u IPv4 18621468       TCP RHEL3:6800 (LISTEN) oracle    22726 oracle9i    4u IPv4 18621469       TCP RHEL3:6800->RHEL3:2174 (CLOSE_WAIT) oracle    22726 oracle9i    8u IPv4 18621568       TCP RHEL3:6800->RHEL3:2175 (CLOSE_WAIT) oracle    22726 oracle9i    9u IPv4 18621578       TCP RHEL3:6800->RHEL3:2176 (CLOSE_WAIT) [oracle9i@RHEL3 oracle9i]$ kill -9 22725 # 22725, 22726就是使用该6800端口的进程号(PID)。 [oracle9i@RHEL3 oracle9i]$ /usr/sbin/lsof -i | grep 6800

进程被kill时,会释放占用的所有链接句柄。 该问题的出现原因网上到处都是,也就是Socket的Client端出现异常没有Close就退出了。

------------------------------------------------------ 本文的资料收集整理自网络.



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有