TCP 是全双工模式,这就意味着
- 客户端主动关闭连接时,会向服务端发送 FIN 报文,这仅表示客户端不再往服务端发送数据了,但仍能接收服务端发来的数据
- 注意 1:只要客户端关闭 socket 的发送能力,Linux 内核就会向服务端发送 FIN 报文
- 注意 2:如果客户端调用 close() 主动关闭连接,这表示客户端既不能再往服务端发送数据,也不能再接收服务端发来的数据,就是说,close() 同时关闭了 socket 的发送和接收能力
- 服务端收到客户端的 FIN 报文后,会回给客户端一个 ACK 报文,但此时服务端可能还有数据需要发送,等服务端没有数据再发送后,才会发送 FIN 报文给客户端,表示同意现在关闭连接
从上述过程可知,服务端通常需要等待完成数据的发送,所以服务端的 ACK 和 FIN 一般都会分开发送,因此是四次挥手,简单地说,前两次挥手用于关闭一个方向的数据通道,后两次挥手用于关闭另外一个方向的数据通道
在特定情况下,四次挥手是可以变成三次的,详见实战 - TCP 四次挥手,可以变成三次吗?(附代码示例)