TCP/IP状态变迁图和TCP三次握手与四次挥手(1)
TCP/IP状态变迁图和TCP三次握手与四次挥手(1)
TCP/IP状态变迁图:
各状态详细描述:
CLOSED:表示初始状态。对服务端和C客户端双方都一样。
LISTEN:表示监听状态。服务端调用了listen函数,可以开始accept连接了。
SYN_SENT:表示客户端已经发送了SYN报文。当客户端调用connect函数发起连接时,首先发SYN给服务端,然后自己进入SYN_SENT状态,并等待服务端发送ACK+SYN。
SYN_RCVD:表示服务端收到客户端发送SYN报文。服务端收到这个报文后,进入SYN_RCVD状态,然后发送ACK+SYN给客户端。
ESTABLISHED:表示连接已经建立成功了。服务端发送完ACK+SYN后进入该状态,客户端收到ACK后也进入该状态。
FIN_WAIT_1:表示主动关闭连接。无论哪方调用close函数发送FIN报文都会进入这个这个状态。
FIN_WAIT_2:表示被动关闭方同意关闭连接。主动关闭连接方收到被动关闭方返回的ACK后,会进入该状态。
TIME_WAIT:表示收到对方的FIN报文并发送了ACK报文,就等2MSL后即可回到CLOSED状态了。如果FIN_WAIT_1状态下,收到对方同时带FIN标志和ACK标志的报文时,可以直接进入TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
CLOSING:表示双方同时关闭连接。如果双方几乎同时调用close函数,那么会出现双方同时发送FIN报文的情况,就会出现CLOSING状态,表示双方都在关闭连接。
CLOSE_WAIT:表示被动关闭方等待关闭。当收到对方调用close函数发送的FIN报文时,回应对方ACK报文,此时进入CLOSE_WAIT状态。
LAST_ACK:表示被动关闭方发送FIN报文后,等待对方的ACK报文状态,当收到ACK后进入CLOSED状态。
1. 连接建立
1) Client
当Client端调用socket函数调用时,相当于Client端产生了一个处于Closed状态的套接字。
Client端又调用connect函数调用,系统为Client随机分配一个端口,连同传入connect中的参数(Server的IP和端口),这就形成了一个连接四元组,connect调用让Client端的socket处于SYN_SENT状态。
当Server返回确认,并发送SYN,Client返回确认及SYN后,套接字处于ESTABLISHED阶段,此时双方的连接已经可以进行读写操作。
2)Server
当Server端调用socket函数调用时,相当于Server端产生了一个处于Closed状态的监听套接字,Server端调用bind操作,将监听套接字与指定的地址和端口关联,然后又调用listen函数,系统会为其分配未完成队列和完成队列,此时的监听套接字可以接受Client的连接,监听套接字状态处于LISTEN状态。
当Server端调用accept操作时,会从完成队列中取出一个已经完成的client连接,同时在server这端会产生一个会话套接字,用于和client端套接字的通信,这个会话套接字的状态是ESTABLISH。
2. 连接关闭
与连接建立分为server/client不同,连接关闭并没有绝对的server/client之分,连接关闭分为主动关闭和被动关闭。Server和client都可以担任这两个角色中的任意一个。如client可以关闭它与server的连接,同样的server一样也可以关闭一些长时间无读写事件发生的连接。既然这么说了,下面就会分成两个部分:client主动关闭,server主动关闭。
Client主动关闭,Server被动关闭:
Client主动关闭,Server被动关闭的情况还是蛮多的,比如说短连接中,当一次会话结束时,client就可以关闭它与server之间的连接。
我们这边直接说close而非shutdown。
当client想要关闭它与server之间的连接,首先client这边会首先调用close函数,client端会发送一个FIN到server端,client端处于FIN_WAIT1状态。当server端返回给client ACK后,client处于FIN_WAIT2状态,server处于CLOSE_WAIT状态。
当server端检测到client端的关闭操作(read返回为0),server端也需要调用close操作,server端会向client端发送一个FIN。此时server的状态为LAST_ACK,当 client收到来自server的FIN后,client端的套接字处于TIME_WAIT状态,它会向server端再发送一个ack确认,此时server端收到ack确认后,此套接字处于CLOSED状态。
Server端主动关闭的流程与Client端关闭类似,就不再多讲,下面还需要关注的是TIME_WAIT这个状态,分别按照client/server两个部分讲述。
首先说一下TCP/IP详解中描述的关于TIME_WAIT的描述及其存在的必要性:
主动关闭的socket当收到对端的FIN操作后,该socket就会处于TIME_WAIT状态,处于TIME_WAIT状态的socket会存活2MSL(Max Segment Lifetime),
之所以存活这么长时间是有理由的:
一方面是可靠的实现TCP全双工连接的终止,也就是当最后的ACK丢失后,被动关闭端会重发FIN,因此主动关闭端需要维持状态信息,以允许它重新发送最终的ACK。
另一方面TCP在2MSL等待期间,定义这个连接(4元组)不能再使用,任何迟到的报文都会丢弃。设想如果没有2MSL的限制,恰好新到的连接正好满足原先的4元组,这时候连接就可能接收到网络上的延迟报文就可能干扰最新建立的连接。重复的分节在网络中消逝。
评论暂时关闭