TCP11种状态分析和测试

  • -->简介
  • -->正文
  • -->测试一些状态

-----------------------------------------------------------------------------------------------------------------------

  • -->简介

  我们都知道TCP有11种状态,那么TCP的这11种状态是在什么情况下产生的呢?我觉得作为学习TCP/IP的我们来说,是一个值得考虑的问题。

  本文主要是基于之前完成的一个C/S的点对点的聊天的程序(需要代码的,可以点击下载),对它进行测试,查看他产生的状态。

  11种状态:

    1、客户端独有的:(1)SYN_SENT (2)FIN_WAIT1 (3)FIN_WAIT2 (4)CLOSING (5)TIME_WAIT 。

    2、服务端独有的:(1)LISTEN (2)SYN_RCVD (3)CLOSE_WAIT (4)LAST_ACK 。

    3、共有的:(1)CLOSED (2)ESTABLISHED 。

    

  • -->正文

    我在网上看到了一张图,这张图被很多人引用过,看上去有点复杂,但是仔细看,确实都介绍清楚了。

    

     三次握手流程

   1、TCP原先的状态是CLOSED,它发送一个SYN包到服务端申请主动打开。 此时,客户端的状态将变为SYN_SENT

     2、服务端通过建立套接字以及调用bind、listen函数,进入了监听状态,此时服务端的TCP状态为LISTEN,它通过被动打开,等待客服端的消息。

     3、服务器收到SYN包,必须确认客户的SYN(ACK=J+1),同时,自己也发送一个SYN包,SYN=K,则此时服务端状态为SYN_RECV

   4、客户端接收到消息后,此时客户端给服务端发送一个ACK,则客户端和服务端状态也转为ESTABLISHED,通过了三次握手,建立了连接。

 

  四次挥手流程:

  1、FIN_WAIT1产生状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT1状态。对方CLOSE一个SOCKET后发送FIN报文给自己,系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。

      2、如果等到了对方的ACK应答,则客户端的状态变为FIN_WAIT2。当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT1状态一般是比较难见到的,而FIN_WAIT2状态还有时常常可以用netstat看到也表示半连接,通俗的说就是对方先告诉你,你先别关闭,我还有点东西要发给你。

  3、接收方收到了对方的FIN报文,并发送了ACK报文,等2MSL后即可回到CLOSED状态。此时的状态为TIME_WAIT状态。

     4、被动关闭的一方收到FIN报文后,等待对方的ACK报文。在等待过程中,TCP状态为LAST_ACK,如果收到了ACK报文,则转为CLOSED。

      5、另外,关于CLOSING状态,百度百科的介绍比较通俗易懂:

      这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也就会出现CLOSING状态,表示双方都正在关闭SOCKET连接。 

 

  • -->测试一些状态

三次握手建立连接后,客户端和服务端都建立连接,此时的状态为ESTABLEISHED。

 

CTRL+C关闭一方后,则刚方进入了TIME_WAIT状态。经过2MSL时间,TIME_WAIT状态消失。

 

 

 

启动客户端echo程序,当主动放关闭时(CTRL+C),另一方并没有关闭,则主动方变为FIN_WAIT2,因为另一放没有发送FIN过来,所以不会变为TIME_WAIT状态。但是测试的时候,再次netstat -at的时候,FIN_WAIT2出现了一会儿就消失了。说明这个进程结束了。

而客户端产生的CLOSE_WAIT状态的原因是:CLOSE_WAIT产生的状态的原因是,当我们主动关闭的那方发送了FIN过去以后,对端主动的回了一个ACK。因为产生了CLOSE_WAIT。而我客户端 并没有发送FIN过去。因此,服务端是不会进入LAST_ACK 。

 

另外:我考虑了一下,FIN_WAIT1这个状态,可以用SHUTDOWN来做,发送FIN的时候,另一方关闭读即可产生FIN_WAIT1状态。其他的一些状态比较难捕捉到。我还没有想到很好的方法。如果想到了,再补上吧。有错误的地方,也希望网友指正。

posted on 2015-08-06 13:40  Mereyct  阅读(1604)  评论(1编辑  收藏  举报

导航