当前位置: 首页 > 科技观察

好不容易终于搞明白TCP的11种状态了,,

时间:2023-03-14 21:25:36 科技观察

本来想在运维过程中写下nginx服务器中time_wait相关的测试和解决方案,后来发现需要TCP的状态先铺好,所以写了整理这篇文章。网上很多大佬整理了TCP的三向握手和四向挥手。看到很多人写的,其实从运维的角度来说,我们在分析TCP连接状态的时候,先用netstat或者ss来查看。之后会根据TCP的状态进行抓包分析,进一步确认一些问题,所以我们首先看到的是TCP的状态,接下来我们需要清楚的了解TCP的11种状态代表什么。TCP的11种状态分别对应TCP三次握手过程的5种状态和TCP四次握手过程的6种状态。如上图所示,有11个状态。在整个TCP连接建立和断开的过程中,我使用tcpdump抓取了一个完整的客户端和服务端的三次握手和四次握手包,可以对应上面的状态图。让我们分别仔细看看。首先是三次握手。上图就是完整的三次握手过程。首先客户端发送连接请求,即SYN=1ACK=0。TCP规定SYN=1不能携带数据,但是会消耗一个seq,所以声明自己的seq=x然后Server会回复确认,即SYN=1ACK=1seq=yack=x+1最后,Client会再次确认,但没有SYN,即ACK=1seq=x+1ack=y+1整个过程中对应的TCP状态如下:CLOSED:初始状态,表示TCP连接是“关闭”还是“未打开”LISTEN:表示服务器端某个SOCKET处于监听状态,可以接受来自客户端的连接SYN_RCVD:表示服务器收到了客户端请求连接的SYN报文.这个状态是在服务器端,但是是一个中间状态,时间很短。通常我们在使用netstat或者ss的时候,是不容易看到这个状态的,但是当遇到SYNflood等SYN攻击的时候,大量的这个状态,三次握手的最后一个client的ACK是无法被看到的收到,所以一直是这个状态,不会转换成ESTABLISHEDSYN_SENT:这个状态对应SYN_RCVD状态,也就是TCP连接客户端的状态。当客户端SOCKET执行connect()连接时,首先发送一个SYN报文,然后随机进入SYN_SENT状态,等待服务器的SYN和ACK。这个状态表示客户端的SYN已经发送ESTABLISHED:表示TCP连接已经成功建立,开始传输数据以上就是三次握手的五个TCP状态。从客户端和服务端来看,CLOSED和ESTABLISHED会出现在客户端和服务端,而LISTEN和SYN_RCVD通常会出现在服务端,而SYN_SENT会出现在客户端但服务端和客户端之间通常不是绝对的边。例如,在Nginx服务器中,Nginx通常被用作Web代理服务器。它既是服务器又是客户端。所以在查询TCP状态统计时,最好通过匹配端口来区分是客户端还是服务端,这样可以更准确的定位问题。再看四次挥手的状态FIN_WAIT_1:这种状态在实际工作中是很少见的。当客户端要主动关闭连接时,会向服务器发送FIN报文,此时TCP状态会进入FIN_WAIT_1。状态,当服务端回复ACK确认关闭后,客户端进入FIN_WAIT_2状态,即只有在没有收到服务端的ACK时才能看到FIN_WAIT_1的状态,之后就不能再收到ACK了收到很久了。通常在默认超时时间60s后(由内核参数tcp_fin_timeout控制),会直接进入CLOSED状态FIN_WAIT_2:该状态比较常见,也是需要注意的状态。FIN_WAIT_1收到服务器的ACK后进入FIN_WAIT_2状态。然后等待服务器发送FIN,所以在收到对端FIN之前,TCP会处于FIN_WAIT_2状态,即当发现主动断开的一端出现大量FIN_WAIT_2状态时,需要注意,网络可能不稳定或者程序可能忘记调用connectionclose,FIN_WAIT_2也有超时时间,也是由内核参数tcp_fin_timeout控制的。当FIN_WAIT_2状态超时,连接直接销毁。CLOSE_WAIT:表示正在等待关闭。这种状态只出现在被动端,即当主动断开端调用close()向被动端发送FIN报文后,被动段必然回应ACK(这是TCP协议层决定的).发短信后,等待对方ACK消息时,处于LAST_ACK状态。收到对方的ACK后,进入CLOSED状态。TIME_WAIT:这种状态是最常见的状态。主动方收到对方的FIN后,从FIN_WAIT_2状态到TIME_WAIT状态CLOSING:这个状态是比较特殊的状态,比较少见。一般情况下不会出现,但是当双方同时作为主动方,调用close()关闭连接时,双方进入FIN_WAIT_1状态。这个时候,他们期望收到一个ACK包,进入FIN_WAIT_2状态,但是他们先收到了对方的FIN包。这时候他们就会进入CLOSING状态,然后给对方一个ACK,收到ACK后直接进入CLOSED状态。以上就是四次挥手的6种状态。了解各个状态的详细含义后,可以在性能调优和故障排除中快速定位问题和调整相关参数。文章开头说了,整理这篇文章主要是铺垫后想整理的nginx中常见的TIME_WAIT问题。TIME_WAIT是否必须快速回收?多少TIME_WAIT太多,会有什么影响,什么时候会产生大量的TIME_WAIT,除了快速回收再利用,还有什么方法可以解决TIME_WAIT的问题,下一篇继续!