概述
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用 四次握手 断开连接
参见 TCP报头格式
四次挥手
特点
由于TCP连接是 全双工 的,因此,每个方向都必须要 单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个 FIN 来终止这一方向的连接,收到FIN只是意味着 不会再收到数据 了,但是在这个TCP连接上仍然能够 发送数据,直到这一方向也发送了FIN。
四次挥手(Four-Way Wavehand),指断开TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。
在socket编程中,这一过程由 客户端 或 服务端 任一方 执行close来触发
第一次挥手
主动方发送数据包,控制位FIN=1,序号seq=u(u是前面发送数据包的序号加1)。
进入FIN_WAIT_1状态
之前主动方和被动方状态都是
ESTABLISHED
第二次挥手
被动方收到数据包后,发送确认包,确认号ack=u+1,序号seq=v(被动方上一次发送数据包的序号加1)
进入CLOSE_WAIT状态
注意:
此时,主动方到被动方,不会发送数据
被动方到主动方的连接并未关闭,仍然可以发送数据

客户端收到数据包后,进入FIN_WAIT_2状态,等待服务器发送关闭连接的报文
第三次挥手
当被动方没有要发送的数据时,发送关闭连接数据包,控制位FIN=1,序号seq=w(在关闭前可能还会发送一些数据包,所以序号不一定是上面的v+1)
进入LAST_ACK状态
第四次挥手
主动方收到数据包后,发送确认包,控制位ACK=1,确认号ack=w+1,序号seq=u+1
进入TIME_WAIT状态
等2MSL后才能返回到CLOSED状态
总结
TCP连接的结束是四次挥手的过程,ACK一直等于1
| 序号 | 方向 | 序号 | 确认号 | FIN | ACK |
|---|---|---|---|---|---|
| 1 | 主动方-被动方 | 80000 | 90000 | 1 | 1 |
| 2 | 被动方-主动方 | 70000 | 80000+1=80001 | 0 | 1 |
| 3 | 被动方-主动方 | 75000 | 80001 | 1 | 1 |
| 4 | 主动方-被动方 | 80001 | 75000+1=75001 | 0 | 1 |
问题
为什么关闭连接是四次握手
- 关闭连接时,当收到主动方的FIN报文通知时,表示主动方没有数据发送了;
- 但被动方可能还有数据要发送给对方,所以不能马上断开连接,还需要发送一些数据
- 然后被动方发送FIN报文,表示没有数据发送给对方,可以断开连接了
什么是MSL?
见https://www.malaoshi.top/show_1EF3OBDZRURN.html
为什么要等待2MSL?
网络是不可靠的,等待 2MSL 时间主要目的是怕最后一个 ACK 没收到。当被动方没有收到第四个包时,会向主动方重复发送FIN报文,所以主动方不能立即关闭
直到2MSL,主动方都没有再次收到FIN,那么主动方就认为ACK已经被成功接收,则断开连接
如果我们设置的时间少于 2MSL ,旧的连接刚刚关闭,这个时候有新连接进来了,而之前的连接还有残留报文在网络上,就会干扰新的连接的使用。
感谢:
https://www.cnblogs.com/zmlctt/p/3690998.html
https://blog.csdn.net/wn_hello/article/details/50066339
https://blog.csdn.net/yeweilei/article/details/79279963



