TCP协议有限状态机分析、概述网络通信中,一个健全的应用程序必须能够处理网络中可能出现的各种状态,必须对TCP的有限状态机有所了解TCP从建立到终止整个过程中,存在11种状态,TCP的有限状 态机给出了 TCP连接从一个状态转到另一个状态的规则二、TCP连接1、建立一个TCP连接TCP使用三次握手(three-way handshake)协议来建立连接,图3-10描述了三次握 手的报文序列这三次握手为:① 请求端(通常称为客户)发送一个SYN报文段(SYN为1)指明客户打算连接的服务 器的端口,以及初始顺序号(ISN)② 服务器发回包含服务器的初始顺序号的SYN报文段(SYN为1)作为应答同时,将 确认号设置为客户的ISN加1以对客户的SYN报文段进行确(ACK也为1 )③ 客户必须将确认号设置为服务器的ISN加1以对服务器的SYN报文段进行确认(ACK发送第一个SYN的一端将执行主动打开(active open),接收这个SYN并发回下一个 SYN的另一端执行被动打开(passive open)另外,TCP的握手协议被精心设计为可以处 理同时打开(simul taneous open),对于同时打开它仅建立一条连接而不是两条连接。
因 此,连接可以由任一方或双方发起,一旦连接建立,数据就可以双向对等地流动,而没有所 谓的主从关系三次握手协议是连接两端正确同步的充要条件因为TCP建立在不可靠的分组传输 服务之上,报文可能丢失、延迟、重复和乱序,因此协议必须使用超时和重传机制如果重 传的连接请求和原先的连接请求在连接正在建立时到达,或者当一个连接已经建立、使用和 结束之后,某个延迟的连接请求才到达,就会出现问题采用三次握手协议(加上这样的规 则:在连接建立之后TCP就不再理睬又一次的连接请求)就可以解决这些问题三次握手协议可以完成两个重要功能:它确保连接双方做好传输准备,并使双方统一了 初始顺序号初始顺序号是在握手期间传输顺序号并获得确认:当一端为建立连接而发送它 的SYN时,它为连接选择一个初始顺序号;每个报文段都包括了顺序号字段和确认号字段, 这使得两台机器仅仅使用三个握手报文就能协商好各自的数据流的顺序号一般来说,ISN 随时间而变化,因此每个连接都将具有不同的ISN 2、关闭一个TCP连接TCP连接建立起来后,就可以在两个方向传送数据流当TCP的应用进程再没有数据需 要发送时,就发关闭命令o TCP通过发送控制位FIN=1的数据片来关闭本方数据流,但还可 以继续接收数据,直到对方关闭那个方向的数据流,连接就关闭。
TCP协议使用修改的三次握手协议来关闭连接,如图3-11所示,即终止一个连接 要经过4次握手这是因为TCP的半关闭(half-close )造成的由于一个TCP连接是 全双工(即数据在两个方向上能同时传递),因此每个方向必须单独地进行关闭关闭的原 则就是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向连接当一端收到 一个FIN,它必须通知应用层另一端已经终止了那个方向的数据传送发送FIN通常是应用从一方的TCP来说,连接的关闭有三种情况:① 本方启动关闭收到本方应用进程的关闭命令后,TCP在发送完尚未处理的报文段后,发FIN=1 的报文段给对方,且TCP不再受理本方应用进程的数据发送在FIN以前发送的数据字节, 包括FIN,都需要对方确认,否则要重传注意FIN也占一个顺序号一旦收到对方对FIN 的确认以及对方的FIN报文段,本方TCP就对该FIN进行确认,在等待一段时间,然后关闭 连接等待是为了防止本方的确认报文丢失,避免对方的重传报文干扰新的连接② 对方启动关闭当TCP收到对方发来的FIN报文时,发ACK确认此FIN报文,并通知应用进程连接正在 关闭应用进程将以关闭命令响应。
TCP在发送完尚未处理的报文段后,发一个FIN报文 给对方TCP,然后等待对方对FIN的确认,收到确认后关闭连接若对方的确认未及时到达, 在等待一段时间后也关闭连接③ 双方同时启动关闭连接双方的应用进程同时发关闭命令,则双方TCP在发送完尚未处理的报文段后,发送 FIN报文各方TCP在FIN前所发报文都得到确认后,发ACK确认它收到的FIN各方在收 到对方对FIN的确认后,同样等待一段时间再关闭连接这称之为同时关闭(simultaneous close)三、TCP状态机TCP协议的操作可以使用一个具有11种状态的有限状态机(Finite State Machine) 来表示,下图描述了 TCP的有限状态机,图中的圆角矩形表示状态,箭头表示状态之间的转 换图中用粗线表示客户端主动和被动的服务器端建立连接的正常过程:客户端的状态变迁 用粗实线,服务器端的状态变迁用粗虚线细线用于不常见的序列,如复位、同时打开、同 时关闭等图中的每条状态变换线上均标有“事件/动作”:事件是指用户执行了系统调用 (CONNECT、LISTEN、SEND 或 CLOSE)、收到一个报文段(SYN、FIN、ACKh 或 RST)、或者 是出现了超过两倍最大的分组生命期的情况;动作是指发送一个报文段(SYN、FIN或ACK) 或什么也没有(用“一”表示)TCP状态转换图瓠按动打7F|熨送:hStAHLiSHLD取邮传输狀遞W」VW: SYNSYN. ACK 同H'l打FCLOSEDLISTENSYN SENT匸动打丿FCLOSh WAIT接枚土 FIN \ rt 发 ££= ACK7<应用:close 或妞时"歲用:I close 戏迭:l F1NLAST ACK■M:ACK変送:接收:ACK发送:CLOSINCi被动关闭触乩超时7CtUJ.com各状态描述1、 LISTEN:侦听来自远方的TCP端口的连接请求2、 SYN-SENT:再发送连接请求后等待匹配的连接请求3、 SYN-RECEIVED:再收到和发送一个连接请求后等待对方对连接请求的确认4、 ESTABLISHED:代表一个打开的连接5、 FIN-WAIT-1 :等待远程TCP连接中断请求,或先前的连接中断请求的确认6、 FIN-WAIT-2:从远程TCP等待连接中断请求7、 CLOSE-WAIT:等待从本地用户发来的连接中断请求8、 CLOSING:等待远程TCP对连接中断的确认9、 LAST-ACK:等待原来的发向远程TCP的连接中断请求的确认10、 TIME-WAIT:等待足够的时间以确保远程TCP接收到连接中断请求的确认11、 CLOSED:没有任何连接状态四、TCP状态转移说明该图描述了 TCP通信主机在传输连接建立和释放过程中的各种有限状态机,图中的方框 中表示的是通信主机在不同时期的状态,箭头表示状态之间的转换,旁边的注释表示状态转 换过程中所需进行动作(包括调用Socket服务原语和TCP数据段的发送和接收等)。
图中 用粗线表示客户端主动和被动的服务器端连接建立的正常过程,其中客户端的状态转移用带 箭头的粗实线表示,服务器端的状态转换用带箭头的粗虚线表示带箭头的细线表示一些不 常见的事件,如复位、同时打开、同时关闭等每个连接均开始于CLOSED状态当一方执行了被动的连接原语(LISTEN )或主动的 连接原语(CONNECT )时,它便会离开CLOSED状态如果此时另一方执行了相对应的连接 原语,连接便建立了,并且状态变为ESTABLISHED任何一方均可以首先请求释放连接, 当连接被释放后,状态又回到了 CLOSED该图包含了两个部分---服务器的状态迁移和客户端的状态迁移为了看清楚客户端和服 务器各自的状态转移流程,我们先沿着带箭头的粗实线路径来看客户端的状态转移过程,然 后再沿着带箭头的虚实线路径来看服务器的状态转移过程W.WTJ收发送收:SYN汽\» 一应用进卑关闭 (SYNJEhjr } ^ 或超时ilV fK ”冋时关闭\K 收:熱伊收:FIN/<: .^CK圭动癸闭A% M懸竺」逅E 、^:ACK j r~i[应用进鶴关闭!1 ' : I ™ ;_ : 1 2 3 i:(lastlackjL 斟址出进稈的关迅 勺主动关厨的 珂KUWAIT丁对專CU061NGACK;J?_ACK j'发迭:无^■^2006-12-22 11:32:10So(CLOSED ”应用港程:被动打开崖选:无被动打幵二严虹星联密CLUJ>csiw―■说阴需户的正常狀注严 一>—*说明服务器的正禽我态蛮迁应用进程1说明当应用执行某种探作时发半的状态变迁收:说明当收到K?报文段时状态的蛮迁4 .上址□口斗'44- 衣 JJi-M 朮 一开始,服务器应用层首先调用LISTEN原语从CLOSED状态进入被动打开状态 (LISTEN ),等待客户端的连接;■〒 TFFi 皿 ¥¥■帛 T 严Tfcln -r4- PTL1、正常状态转换【说明】这里可能有一个非正常事件发生,那就是如果此时服务器不想建立传输连接, 由其应用层调用CLOSE原语,向客户端发送一个FIN数据段(FIN字段置1),然后进入到 FIN WAIT 1状态,等待客户端确认。
当客户端收到服务器发来的FIN数据段后,向服务器 发送一个ACK确认数据段后进入到CLOSING状态,表示双方同时尝试关闭传输连接,等待对 方确认在服务器收到客户端发来的ACK数据段后即进入到TIMED WAIT状态,在超时后双 方即关闭连接这是一种突发、非正常的连接关闭事件4) 客户端在收到服务器发来的SYN和ACK数据段后,其TCP实体给服务器端发送一个 ACK数据段,并进入ESTABLISHED状态这是TCP连接的第3次握手5) 服务器在收到来自客户端的ACK确认数据段后,完成整个TCP传输连接的全部三次 握手过程,也进入ESTABLISHED状态此时,双方可以自由进行数据传输了当一个应用程序完成数据传输任务后,它需要关 闭TCP连接假设仍由客户端发起主动关闭连接6)客户端应用层调用CLOSE原语,本地的TCP实体发送一个FIN数据段(FIN字段 置1),并等待服务器的确认响应,进入到FIN WAIT 1状态说明】这里又可能有一个非正常的事件发生,那就是客户端在FIN WAIT 1状态收到 服务器的FIN和ACK数据段后(而不是像从FIN WAIT 2状态进入那样只收到服务器的ACK 确认数据段),向服务器发送一个ACK数据段,直接就进入了 TIMED WAIT状态。
在超时后 双方即关闭连接7) 服务器在收到来自客户端的FIN数据段后,它给客户端发回一个ACK数据段(ACK 字段置1)进入CLOSE WAIT状态8) 客户端在收到来自服务器的ACK确认数据段后就进入到了 FIN WAIT 2状态,此时 连接在一个方向上就断开了,但仍可以接收服务器端发来的数据段9) 当服务器收到客户端发来的FIN数据段时就知道客户端已有数据发送了,在本端已 接收完全部的数据后,也由应用层调用CLOSE原语,请求关闭另一个方向的连接,其本地 TCP实体向客户端发送一个FIN数据段,并进入LAST ACK状态,等待最后一个ACK确认数 据段10) 在客户端收到来自服务器的FIN数据段后,向服务器发送最后一个ACK确认数据 段,进入TIMED WAIT状态此时双方连接均已经断开,但TCP实体仍要等待一个2倍数据 段MSL(Maximum Segmen t Life time最大数据段生存时间),以确保该连接的所有分组全 部消失,防止出现确认丢失的情况当定时器超时后,TCP删除该连接记录,返回到初始状 态(CLOSED )11) 服务器收到客户端最后一个ACK确认数据段后,其TCP实体便释放该连接,并删 除连接记录,也返回到初始状态(CLOSED )。
服务器图18J3 TCT正常连接建立和终止所对刍5^舄常2、同时打开尽管发生的可能性极小,两个应用程序同时彼此执行主动打开的情况还是可能的每一 方必须发送一个SYN,且这些SYN必须传递给对方这需要每一方使用一个对方周知的端 口作为本地端口例如,主机A中的一个应用程序使用本地端口 7777,并与主机B的端 口 8888执行主动打开主机B中的应用程序则使用本地端口 8888,并与主机A的端口 7777执行主动打开TCP是特意设计为了可以处理同时打开,对于同时打开它仅建立一条 连接而不是两条连接(其他的协议族,最突出的是OSI传输层,在这种情况下将建立两条 连接而不是一条连接)当出现同时打开的情况时,状态变迁与图3-13所示的不同两端几乎在同时发送SYN, 并进入SYN_SENT状态当每一端收到SYN时,状态变为SYN_RCVD,同时它们都再发SYN 并对收到的SYN进行确认当双方都收到SYN及相应的ACK时,状态都变迁为ESTABLISHED一个同时打开的连接需要交换4个报文段,比正常的三次握手多一个此外,要注意 的是我们没有将任何一端称为客户或服务器,因为每一端既是客户又是服务器3、同时关闭正常情况下都是由一方(通常但不总是客户方)发送第一个FIN执行主动关闭,但双 方都执行主动关闭也是可能的,TCP协议也允许这样的同时关闭。
当两端应用层同时发出关 闭命令时,两端均从ESTABLISHED变为FIN_WAIT_1这将导致双方各发送一个FIN,两个 FIN经过网络传送后分别到达另一端收到FIN后,状态由FIN_WAIT_1变迁到CLOSING, 并发送最后的ACK当收到最后的ACK时,状态变化为TIME_WAIT下图这些状态的变化,从图中可以看出同时关闭与正常关闭使用的报文段交换数目相同4、其他状态迁移图中还有一些其他的状态迁移,这些状态迁移针对服务器和客户端两方面的总结如下:① LISTEN-〉SYN_SENT,对于这个解释就很简单了,服务器有时候也要打开连接的② SYN_SENT-〉SYN收到,服务器和客户端在SYN_SENT状态下如果收到SYN数据报,则都需 要发送SYN的ACK数据报并把自己的状态调整到SYN收到状态,准备进入ESTABLISHED③ SYN_SENT-〉CLOSED,在发送超时的情况下,会返回到CLOSED状态④ SYN_收到-〉LISTEN,如果受到RST包,会返回到LISTEN状态⑤ SYN_收到-〉FIN_WAIT_1,这个迁移是说,可以不用到ESTABLISHED状态,而可以直接跳转 到FIN_WAIT_1状态并等待关闭。
⑥ MSL等待状态图中有一个TIME_WAIT等待状态,这个状态又叫做2MSL状态,说的是在TIME_WAIT2 发送了最后一个ACK数据报以后,要进入TIME_WAIT状态,这个状态是防止最后一次握手的 数据报没有传送到对方那里而准备的(注意这不是四次握手,这是第四次握手的保险状态) 这个状态在很大程度上保证了双方都可以正常结束,但是,问题也来了,由于插口的2MSL 状态(插口是IP和端口对的意思,socket),使得应用程序在2MSL时间内是无法再次使用 同一个插口的,对于客户程序还好一些,但是对于服务程序,例如httpd,它总是要使用同 一个端口来进行服务,而在2MSL时间内,启动httpd就会出现错误(插口被使用)为了 避免这个错误,服务器给出了一个平静时间的概念,这是说在2MSL时间内,虽然可以重新 启动服务器,但是这个服务器还是要平静的等待2MSL时间的过去才能进行下一次连接⑦ FIN_WAIT_2 状态这就是著名的半关闭的状态了,这是在关闭连接时,客户端和服务器两次握手之后的状 态在这个状态下,应用程序还有接受数据的能力,但是已经无法发送数据,但是也有一种 可能是,客户端一直处于FIN_WAIT_2状态,而服务器则一直处于WAIT_CLOSE状态,而直到 应用层来决定关闭这个状态。
2) 当客户端的一个应用程序调用CONNECT原语后,本地的TCP实体为其创建一个连接 记录并标记为SYN SENT状态,然后给服务器发送一个SYN数据段(SYN字段置1)这是 TCP传输连接建立的第一次握手3) 服务器在收到一个客户端的SYN数据段后,其TCP实体给客户端发送确认ACK数据 段(ACK字段置1),同时发送一个SYN数据段(SYN字段置1,表示接受同步请求),进入 SYN RCVD状态这是TCP传输连接的第2次握手。