TCP
连接是双向传输的对等的模式(全双工模式),就是说双方都可以同时向对方发送或接收数据。
而断开的时候,也是双方都可以主动断开,此时需要经过四次挥手的过程,流程如下图所示:
- 主动方发送
FIN
包给被动方,主动方状态变成FIN_WAIT_1
,等待被动方的确认。此时主动方不能再发送数据。 - 被动方收到
FIN
之后,返回ACK
包给主动方,确认自己收到这个包,被动方状态变成CLOSE_WAIT
,等待关闭连接(等待缓存数据都发送过去) - 主动方收到
ACK
之后,状态变成FIN_WAIT_2
,等待被动方的FIN
包。 - 被动方将缓冲区剩余的数据发送给主动方。
- 被动方发送
FIN
给主动方,被动方状态变成LAST_ACK
状态。 - 主动方收到
FIN
之后,返回ACK
包给被动方,主动方变成TIME_WAIT
状态。 - 被动方收到
ACK
确认后,变成CLOSE
状态。 - 主动方在经过
2MSL
时间之后,变成CLOSE
状态。
MSL(Maximum Segment Lifetime)指报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
为什么握手需要三次,而挥手需要四次?
因为 TCP
连接是全双工模式,一方断开连接,另一方还是可以继续发送数据,所以无法像三次握手一样,将 FIN
和 ACK
合并到一起,而是需要等待被动方处理完所有数据,不再有数据发送时,才会发送 FIN
,来关闭被动方的连接。
为什么需要 TIME_WAIT
状态?
需要 TIME_WAIT
状态,主要是两个原因:
- 防止历史连接中的数据,被后面相同四元组的连接错误的接收:
在连接关闭过程中,可能会存在一些延迟的数据包在网络中,这些数据包可能在连接关闭后到达目的地。TIME_WAIT
状态的存在可以确保在这段时间内不会接收到与当前连接相关的旧数据包,防止这些数据包造成连接的混乱。 - 保证「被动关闭连接」的一方,能被正确的关闭:
如果主动方收到FIN
,发出ACK
之后,直接进入CLOSE
状态,那么当这个ACK
丢失时,被动方收不到ACK
则会重发一个FIN
,但此时主动方已经是CLOSE
状态,无法再给被动方发送ACK
了。
如果两端同时关闭,会出现什么情况?
前面说过,TCP
连接双方都可以主动断开,那如果两边同时断开,会怎样呢?
从上图可以看到,一方发出FIN
,进入FIN_WAIT_1
状态,原本期待收到ACK
,但此时收到了FIN
,则会变成CLOSING
状态,等到收到ACK
时,再进入TIME_WAIT
状态,同样要经过2MSL
时间变成CLOSE
状态。