最常见的四次挥手的过程下图所示
- 客户端调用 close 方法,执行「主动关闭」,会发送一个 FIN 报文给服务端,从这以后客户端不能再发送数据给服务端了,客户端进入FIN-WAIT-1状态。FIN 报文其实就是将 FIN 标志位设置为 1。
- FIN 段可携带数据
- 半关闭状态
- 服务端收到 FIN 包以后回复确认 ACK 报文给客户端,服务端进入 CLOSE_WAIT,客户端收到 ACK 以后进入FIN-WAIT-2状态。
- 服务端也没有数据要发送了,发送 FIN 报文给客户端,然后进入LAST-ACK 状态,等待客户端的 ACK。同前面一样如果 FIN 段没有携带数据,也需要消耗一个序列号。
- 客户端收到服务端的 FIN 报文以后,回复 ACK 报文用来确认第三步里的 FIN 报文,进入TIME_WAIT状态,等待 2 个 MSL 以后进入 CLOSED状态。服务端收到 ACK 以后进入CLOSED状态。
为什么 FIN 报文要消耗一个序列号
为什么挥手要四次,变为三次可以吗?
可以是三次:
wireshark 抓包:
握手可以变为四次吗?
其实理论上完全是可以的,把三次握手的第二次的 SYN+ACK 拆成先回 ACK 包,再发 SYN 包就变成了「四次握手」
- 握手的时候不携带数据, 没必要分成四次
同时关闭
可以两端同时发起 FIN 包:
以客户端为例:
- 最初客户端和服务端都处于 ESTABLISHED 状态
- 客户端发送 FIN 包,等待对端对这个 FIN 包的 ACK,随后进入 FIN-WAIT-1 状态
- 处于FIN-WAIT-1状态的客户端还没有等到 ACK,收到了服务端发过来的 FIN 包
- 收到 FIN 包以后客户端会发送对这个 FIN 包的的确认 ACK 包,同时自己进入 CLOSING 状态继续等自己 FIN 包的 ACK
- 处于 CLOSING 状态的客户端终于等到了ACK,随后进入TIME-WAIT
- 在TIME-WAIT状态持续 2*MSL,进入CLOSED状态
文字和图示不匹配, 应该以文字为准.