TCP状态转换图解析

本文参考Unix网络编程卷1,对TCP状态转换进行总结,方便掌握TCP链接中各个状态及故障分析。

1.Linux下TCP相关工具

  基于Linux系统查看网络状态,首先了解几个基本查看指令。

Linux查看网络状态的命令:

  1. netstat -nat  查看TCP各个状态的数量
  2. lsof  -i:port , 可以检测到打开套接字的状况。lsof(list open files)列出当前系统打开的文本的工具。
  3. tcpdump -iany tcp port 9000 ,对tcp端口为9000的进行抓包。 tcpdump为Linux下的抓包工具。
  4. sar -n SOCK 查看tcp创建的连接数

 网络测试使用的Linux命令:、

  1.ping:检测网络连接的正常与否,主要是测试延时、抖动、丢包率。

    ping命令使用ICMP协议,用于测试网络的连通性,可以通过接受到的返回值简单查看测试网络经过的路由数(由TTL值判断)及网络延迟时间。

  2.traceroute: 跟踪数据包到达网络主机所经过的路由工具

    使用方法:traceroute hostname

  3.pathping:是一个路由跟踪工具,它将 ping 和 tracert 命令的功能与这两个工具所不提供的其他信息结合起来,综合了二者的功能。

    使用方法:pathping www.baidu.com

  4.mtr:以结合ping nslookup tracert 来判断网络的相关特性。

  5.nslookup:用于解析域名,一般用来检测本机的DNS设置是否配置正确。

2.TCP状态

  使用netstat命令查看TCP连接,在每个连接后会显示连接状态,各个状态说明如下:

  1.LISTEN:侦听来自远方的TCP端口的连接请求(服务器端进入监听状态)

    首先TCP连接服务器打开一个socket连接,在进行Listen函数调用后,绑定端口编程LISTEN状态。

    处于侦听LISTENING状态时,该端口是开放的,等待连接,但还没有被连接。就像你房子的门已经敞开的,但还没有人进来。

  2.SYN-SENT:再发送连接请求后等待匹配的连接请求(客户端发送连接请求后)

      客户端在发送连接请求后等待匹配的连接请求:客户端通过应用程序调用connect进行active open.于是客户端tcp发送一个SYN以请求建立一个连接.之后状态置为SYN_SENT.

  3.SYN-RECEIVED:再收到和发送一个连接请求后等待对方对连接请求的确认(服务端接收到SYN后发送确认,等待客户端对此确认的确认)

     在收到和发送一个连接请求后等待对方对连接请求的确认。

    当服务器收到客户端发送的同步信号时,将标志位ACK和
    如果发现有很多SYN_RCVD状态,那你的机器有可能被SYN Flood的DoS(拒绝服务攻击)攻击了。

  SYN Flood的攻击原理是:

  在进行三次握手时,攻击软件向被攻击的服务器发送SYN连接请求(握手的第一步),但是这个地址是伪造的,如攻击软件随机伪造了51.133.163.104、65.158.99.152等等地址。服务器在收到连接请求时将标志位ACK和SYN置1发送给客户端(握手的第二步),但是这些客户端的IP地址都是伪造的,服务器根本找不到客户机,也就是说握手的第三步不可能完成。

   这种情况下服务器端一般会重试(再次发送SYN+ACK给客户端)并等待一段时间后丢弃这个未完成的连接,这段时间的长度我们称为SYN Timeout,一般来说这个时间是分钟的数量级(大约为30秒-2分钟);一个用户出现异常导致服务器的一个线程等待1分钟并不是什么很大的问题,但如果有一个恶意的攻击者大量模拟这种情况,服务器端将为了维护一个非常大的半连接列表而消耗非常多的资源----数以万计的半连接,即使是简单的保存并遍历也会消耗非常多的

  4.ESTABLISHED:代表一个打开的连接(三次握手进行完毕)
    状态为ESTABLISHED表示此端口处于连接状态,正在进行数据传输。

    异常及原因:
    客户端正常断开时会发送FIN报给服务端,此后服务端处于CLOSE_WAIT状态。

    客户端非正常断开时不会发送FIN报给服务端,服务端将长期处于ESTABLISHED状态。

    如果客户端不断重复掉线-连接过程,服务端将会出现大量的无效的ESTABLISHED和CLOSE_WAIT,导致资源耗尽,新的客户端无法连接(netstat仍可看到ESTABLISHED状态但是无法进行数据传输)

  5.FIN-WAIT-1:等待远程TCP连接中断请求,或先前的连接中断请求的确认(主动发送FIN报后)
     主动关闭(active close)端应用程序调用close,于是其TCP发出FIN请求主动关闭连接,之后进入FIN_WAIT1状态。

     如果服务器出现shutdown再重启,使用netstat -nat查看,就会看到很多FIN-WAIT-1的状态。就是因为服务器当前有很多客户端连接,直接关闭服务器后,无法接收到客户端的ACK。
  6.FIN-WAIT-2:从远程TCP等待连接中断请求(接收到FIN的ACK后)
      主动关闭端接到ACK后,就进入了FIN-WAIT-2  状态。

      这就是著名的半关闭的状态了,这是在关闭连接时,客户端和服务器两次握手之后的状态。在这个状态下,应用程序还有接受数据的能力,但是已经无法发送数据,但是也有一种可能是,客户端一直处于    FIN_WAIT_2状态,而服务器则一直处于WAIT_CLOSE状态,而直到应用层来决定关闭这个状态。
  7.CLOSE-WAIT:等待从本地用户发来的连接中断请求(服务端接收到FIN并发送ACK后)
    服务端接收到远程客户端发送的FIN报并发送ACK进行确认后等待本地用户发送的中断请求期间处于CLOSE-WAIT状态。
  8.CLOSING:等待远程TCP对连接中断的确认(尚不清楚状态)
    不常见
  9.LAST-ACK:等待原来的发向远程TCP的连接中断请求的确认(服务端发送FIN后等待客户端的ACK)
    被动关闭端(服务端)一段时间后,接收到文件结束符的应用程序将调用CLOSE关闭连接。这导致它的TCP也发送一个 FIN,等待对方的ACK.就进入了LAST-ACK
  10.TIME-WAIT:等待足够的时间以确保远程TCP接收到连接中断请求的确认(客户端接收到FIN后发送ACK,等待确保服务端接收到此ACK)
    在客户端接收到FIN后,TCP就发送ACK包,并进入TIME-WAIT状态。

    此等待时间可能造成的问题:

    TIME_WAIT等待状态,这个状态又叫做2MSL状态,说的是在TIME_WAIT2发送了最后一个ACK数据报以后,要进入TIME_WAIT状态,这个状态是防止最后一次握手的数据报没有传送到对方那里而准备的(注  意这不是四次握手,这是第四次握手的保险状态)。这个状态在很大程度上保证了双方都可以正常结束,但是,问题也来了。

  由于插口的2MSL状态(插口是IP和端口对的意思,socket),使得应用程序在2MSL时间内是无法再次使用同一个插口的,对于客户程序还好一些,但是对于服务程序,例如httpd,它总是要使用同一个端口来进  行服务,而在2MSL时间内,启动httpd就会出现错误(插口被使用)。为了避免这个错误,服务器给出了一个平静时间的概念,这是说在2MSL时间内,虽然可以重新启动服务器,但是这个服务器还是要平静的等  待2MSL时间的过去才能进行下一次连接。

  11.CLOSED:没有任何连接状态(服务端接收到ACK后进入)

3.TCP状态转换图

  如下转换图展示了服务端和客户端的状态转换关系。

    

TCP连接中的3次握手及4次挥手示意图:

      

客户端应用程序的状态迁移图

客户端的状态可以用如下的流程来表示:

CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED

以上流程是在程序正常的情况下应该有的流程,从书中的图中可以看到,在建立连接时,当客户端收到SYN报文的ACK以后,客户端就打开了数据交互地连接。而结束连接则通常是客户端主动结束的,客户端结束应用程序以后,需要经历FIN_WAIT_1,FIN_WAIT_2等状态,这些状态的迁移就是前面提到的结束连接的四次握手。

服务器的状态迁移图

服务器的状态可以用如下的流程来表示:

CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED

在建立连接的时候,服务器端是在第三次握手之后才进入数据交互状态,而关闭连接则是在关闭连接的第二次握手以后(注意不是第四次)。而关闭以后还要等待客户端给出最后的ACK包才能进入初始的状态。

4.TCP状态转换中部分难点

  1.什么是半打开连接?什么是半关闭连接?

    TCP的半开连接(half-open)是指TCP连接的一端崩溃,或者在未通知对端的情况下移除socket,不可以正常收发数据,否则会产生RST。

    TCP的半关闭是指TCP连接的一端调用shutdown操作使数据只能往一个方向流动,只有一方发送了FIN,仍然可以正常收(或发)数据。

  2..为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?

    这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发    送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下    都是分开发送的。

  3.为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?

      这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样):

     一方面是可靠的实现TCP全双工连接的终止,也就是当最后的ACK丢失后,被动关闭端会重发FIN,因此主动关闭端需要维持状态信息,以允许它重新发送最终的ACK。

      另一方面,但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用    就是用来重发可能丢失的ACK报文。

     TCP在2MSL等待期间,定义这个连接(4元组)不能再使用,任何迟到的报文都会丢弃。设想如果没有2MSL的限制,恰好新到的连接正好满足原先的4元组,这时候连接就可能接收到网络上的延迟报文就可能    干扰最新建立的连接。

  4.发现系统存在大量TIME_WAIT状态的连接,可以通过调整内核参数解决: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,表示关闭。
    net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间

时间: 2024-10-10 13:39:41

TCP状态转换图解析的相关文章

传输控制协议(TCP) -- TCP状态转换图

本文参考自: <UNIX网络编程 卷1> 在<UNIX网络编程 卷1>一书中,作者给出了TCP状态转换图(如下).本文也将围绕此图进行阐释.

TCP状态转换图(state transition diagram)

 TPC总共有11个状态,状态转换图: 状态转换的要素 状态: tcp定义的11个状态 事件: 触发TCP状态迁移.事件可以是:本地应用层调用:收到TCP消息(incoming segment):超时事件(timeout) 动作: 主要指针对远程Peer产生的动作,如发送确认等. 转换中的角色 本地应用层 Local App:产生事件. 本地tcp实现层 local TCP stack:处理事件,完成状态转换:在远程tcp上产生事件. 远程tcp实现层 remote TCP stack(or

TCP的三次握手以及TCP状态转换图详解

今天来讨论一下TCP的三次握手以及TCP的状态转换图.首先发一个三次握手的流程图如下: 圖 2.4-3.三向交握之封包连接模式A:封包发起当用戶端想要对服务器端发起连接时,就必須要送出一個要求连线的封包,此时用戶端必须随机取用一個大于1024 以上的端口來做为程序通信的通道.然后在 TCP 的表头当中,必须带有 SYN 的主动连线(SYN=1),並并且记下发送给服务器端的序列号(Sequence number = 10001) .B:封包接收与确认封包发送当服务器端收到这个包,并且确定要接受这个

TCP状态转换图

TCP连接的建立与终止可以用状态转换图(state transition diagram)来说明,见图2.4. 图中定义了11种状态,这种转换基于 如果一个client进程调用close(),主动发送一个SYN--->SYN_SENT状态,这时握手成功收到server的syn和ACK,发回Client ACK然后,进入ESTABLISHED状态.建立TCP的三次握手过程. 四次握手的关闭过程. 在SYN_SENT的状态下接收SYN关键字时,转入SYN_RCVD状态,继续接收server端的传输数

TCP三次握手、四次挥手及状态转换图

TCP/IP通信的三次握手如下: TCP是主机对主机层的传输控制协议,提供可靠的连接服务: 位码即tcp标志位,有6种标示:SYN(synchronous建立联机) .ACK(acknowledgement 确认) .PSH(push传送). FIN(finish结束) .RST(reset重置) .URG(urgent紧急).Sequence number(顺序号码) .Acknowledge number(确认号码). 三次握手: 第一次握手:客户端发送syn包(syn=x)的数据包到服务器

读懂TCP状态转移

读懂TCP状态变换的过程,对于理解网络编程颇有帮助,本文将对TCP状态转移过程进行介绍,但各个状态(总共11个)的含义不在本文介绍的范围. 内容来源:<UNIX网络编程>第一卷第二章2.6节,若是读者对某个知识点不太理解,请参考原文. TCP状态转换图(state transition diagram) 1. 建立连接(three-way hand shake) 主动打开(passive open):服务器必须准备好接受外来的连接,通常通过socket.bind和listen完成. 被动打开(

TCP四步挥手的各种状态转换图

对于TCP四步挥手时的各种状态转换,网上有很多资料.但是有很多描述不是很容易理解,甚至是描述错误,不如这篇文章里http://www.cnblogs.com/Jessy/p/3535612.html#3428191 说: 对此我表示不以为然.而且很容易误导初学者.在这里我贴出一个网上画的比较好的TCP四步挥手时的状态转换图:

TCP状态迁移,CLOSE_WAIT &amp; FIN_WAIT2 的问题

TCP状态迁移 大家对netstat -a命令很熟悉,但是,你有没有注意到STATE一栏呢,基本上显示着established,time_wait,close_wait等,这些到底是 什么意思呢,在这篇文章,我将会详细的阐述. 大家很明白TCP初始化连接三次握手吧:发SYN包,然后返回SYN/ACK包,再发ACK包,连接正式建立.但是这里有点出入,当请求者收到SYS /ACK包后,就开始建立连接了,而被请求者第三次握手结束后才建立连接.但是大家明白关闭连接的工作原理吗?关闭连接要四次握手:发FI

zabbix3.0 使用SS代替netstat无需脚本,1分钟搞定TCP状态监控

这段时间一直忙,没时间好好理下监控,趁着假期有时间,理了一下. 对于zabbix监控TCP状态,在网上查了很多资料,大多数都是使用netstat命令来实现. 如果服务器的压力小,链接少,不会有问题,但随着服务器压力和链接数的增加,用netstat就会造成执行速度慢,server端无法接收到执行结果,造成监控异常. 平时一直用SS,所以试着用SS代替netstat,速度快了不少. 个人较喜欢偷懒,看到网上很多少写了非常长的脚本,又是函数,又是写临时文件的.其实完全没必要,不用写啥脚本,临时文件,很