程序员社区

TCP状态转换

TCP在三次握手和四次挥手的过程中,会经历不同的状态转换

三次握手与四次挥手

TCP的状态转换是伴随着三次握手和四次挥手发生的

TCP状态转换插图

状态转换图

通过《UNIX网络编程卷一》中的TCP状态转换图,更详细了解TCP状态转换

最上面的CLOSED只代表状态的起点

CLOSED

起始点,在超时或者连接关闭时候进入此状态,这并不是一个真正的状态,而是这个状态图的假想起点和终点

LISTEN

服务器端等待连接的状态。服务器经过 socket,bind,listen 函数之后进入此状态,开始监听客户端发过来的连接请求。此称为应用程序被动打开(等到客户端连接请求)

SYN_SENT

第一次握手发生阶段,客户端发起连接。客户端调用 connect,发送 SYN 给服务器端,然后进入 SYN_SENT 状态,等待服务器端确认(三次握手中的第二个报文)。如果服务器端不能连接,则直接进入CLOSED状态

SYN_RCVD

第二次握手发生阶段,服务器端接收客户端的 SYN,此时服务器由 LISTEN 进入 SYN_RCVD状态,同时服务器端回应一个 ACK+SYN 给客户端。状态图中还描绘了这样一种情况,当客户端在发送 SYN 的同时也收到服务器端的 SYN请求,即两个同时发起连接请求,那么客户端就会从 SYN_SENT 转换到 SYN_REVD 状态

ESTABLISHED

第三次握手发生阶段,客户端接收到服务器端的 ACK+SYN 包后,回复一个 ACK 确认包,客户端立刻进入 ESTABLISHED 状态,表明客户端这边已经准备好,但TCP 需要两端都准备好才可以进行数据传输。服务器端收到客户端的 ACK 之后会从 SYN_RCVD 状态转移到 ESTABLISHED 状态,表明服务器端也准备好进行数据传输了。这样客户端和服务器端都是 ESTABLISHED 状态,就可以进行后面的数据传输了。所以 ESTABLISHED 也可以说是一个数据传送状态

FIN_WAIT_1

主动关闭的一方(执行主动关闭的一方既可以是客户端,也可以是服务器端,这里以客户端执行主动关闭为例),终止连接时,发送 FIN 给对方,然后等待对方返回 ACK 。调用 close() 第一次挥手就进入此状态

CLOSE_WAIT

接收到FIN 之后,同时发送ACK,被动关闭的一方进入此状态。之所以叫 CLOSE_WAIT 可以理解为被动关闭的一方此时正在等待上层应用程序发出关闭连接指令。前面已经说过,TCP关闭是全双工过程,这里客户端执行了主动关闭,被动方服务器端接收到FIN 后也需要调用 close 关闭,这个 CLOSE_WAIT 就是处于这个状态,等待发送 FIN,发送了FIN 则进入 LAST_ACK 状态

FIN_WAIT_2

主动端(这里是客户端)接收到被动方返回的 ACK 后进入此状态

LAST_ACK

被动方(服务器端)发起关闭请求,发送 FIN给对方后,进入此状态

CLOSING

主动方发送完FIN后进入FIN_WAIT_1,在等待被动方的ACK时,没有等到ACK,反而等来了被动方的FIN,意味着被动方也发起了主动关闭请求,主动方回复ACK后,进入CLOSING

TIME_WAIT

从状态变迁图会看到,四次挥手操作最后都会经过这样一个状态然后进入CLOSED状态。共有三个状态会进入该状态

  • 由CLOSING进入:

同时发起关闭情况下,当主动端接收到ACK后,进入此状态,实际上这里的同时是这样的情况:客户端发起关闭请求,发送FIN之后等待服务器端回应ACK,但此时服务器端同时也发起关闭请求,也发送了FIN,并且被客户端先于ACK接收到

  • 由FIN_WAIT_1进入:

发起关闭后,发送了FIN,等待ACK的时候,正好被动方(服务器端)也发起关闭请求,发送了FIN,这时客户端接收到了先前ACK,也收到了对方的FIN,然后发送ACK(对对方FIN的回应),与CLOSING进入的状态不同的是接收到FIN和ACK的先后顺序

  • 由FIN_WAIT_2进入:

这是不同时的情况,主动方在完成自身发起的主动关闭请求后,接收到了对方发送过来的FIN,然后回应 ACK

由FIN_WAIT_1到TIME_WAIT有三条路径,也就是主动关闭时会发生的三种情况:

  • FIN_WAIT_1—>FIN_WAIT_2—>TIME_WAIT

主动方发送FIN请求关闭连接,被动方接收到后,发现自己还有数据没发完,先给主动方回复一个ACK,主动方收到这个ACK后进入FIN_WAIT_2,被动方发送完数据后,调用close(),发FIN给主动方,主动方收到FIN,回复ACK,进入TIME_WAIT

  • FIN_WAIT_1—>CLOSING—>TIME_WAIT

主动方发送FIN请求关闭连接,这个FIN还没到被动方,被动方恰好也想主动关闭TCP连接,给主动方发送FIN,主动方收到FIN后回复ACK,进入CLOSING,被动方收到FIN后回复ACK,主动方收到ACK后,进入TIME_WAIT

  • FIN_WAIT_1—>TIME_WAIT

主动方发送FIN请求关闭连接,被动方接收到后,发现自己没有数据要发送,就把ACK和FIN放在一起发出,主动方收到后,直接进入TIME_WAIT

可以总结出:

主动方发送FIN,要么是未到达前对方主动关闭,要么是到达了,对方先回ACK,或者ACK+FIN一起发


赞(0) 打赏
未经允许不得转载:IDEA激活码 » TCP状态转换

相关推荐

  • 暂无文章

一个分享Java & Python知识的社区