当客户端和服务器通过三次握手建立了 TCP 连接以后,当数据传送完毕,肯定是要断开 TCP 连接的。那对于 TCP 的断开连接,就有了四次挥手(TCP Four-way Wavehand)。
四次挥手(TCP Four-way Wavehand)
由于 TCP 连接是全双工的,因此每个方向的连接必须单独地进行关闭,于是 TCP 连接的断开需要进行 “四次挥手”(两端分别进行 FIN+ACK 和 ACK 两次挥手)。
TCP 连接断开的过程:
- 客户端发起请求,向服务端发送一个 FIN 报文段(其中 Seq = x, Ack = l),用来关闭从客户端到服务端的传输。客户端的状态变为 FIN_WAIT_1 状态。此时客户端仍然可以接收数据。如果这之前发出的数据中存在没有 ACK 的,客户端仍然会重发这些数据。
- 服务端收到客户端的 FIN 包,然后向客户端发回一个 ACK 报文段(Ack = x + 1, Seq = l)作为确认,此后服务端进入 CLOSE_WAIT 状态。
- 同时,服务端向客户端发送一个 FIN 报文段(Seq = l, Ack = x + 1),用来关闭从服务端到客户端的传输,此后服务端的状态变为 LAST_ACK。
- 客户端收到服务端发送的 FIN 报文段后,进入 TIME_WAIT 状态,然后向服务端发回一个 ACK 包(Ack = l + 1, Seq = x + 1)作为确认。服务端收到后,Server 进入 CLOSED 状态。最终四次挥手结束,连接断开(CLOSE)。
注意:TIME_WAIT 状态需要经过 2MSL(最大报文段生存时间)才能返回到 CLOSED 状态,原因:
- TIME_WAIT 确保有足够的时间让对端收到了 ACK(如果被动关闭的那方没有收到 ACK,就会触发被动端重发 FIN,一来一去正好 2 个 MSL)
- 有足够的时间让这个连接不会跟后面的连接混在一起(部分路由器会缓存数据包导致连接重用)
以下为动画演示四次挥手的交互过程:
四次握手时的状态变化
为什么要四次挥手
TCP 协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。TCP 是全双工模式,这就意味着:
- 当主机 1 向主机 2 发出 FIN 报文段时,只是表示主机 1 已经没有数据要发送了,即主机 1 告诉主机 2,它的数据已经全部发送完毕了;
- 但是,这个时候主机 1 还是可以接受来自主机 2 的数据;当主机 2 返回 ACK 报文段时,表示它已经知道主机 1 没有数据发送了,但是主机 2 仍然还是可以发送数据到主机 1 的;
- 当主机 2 也发送了 FIN 报文段时,这个时候就表示主机 2 也没有数据要发送了,就会告诉主机 1,我也没有数据要发送了,之后彼此就会愉快的中断这次 TCP 连接。
Wireshake 抓包学习 TCP 四次挥手
可以增加 tcp && tcp.flags.fin == 1
过滤条件,可以让我们找到两条 FIN 报文段。去掉过滤条件,并找到这两条 FIN 报文段对应的 ACK 报文段。
一个完整的四次挥手过程如下所示:
分析
#6939
Client -> Server
[FIN, ACK]
Sequence number 196
Acknowledgement number: 1689
#6941
Server -> Client
[ACK]
Sequence number 1689
Acknowledgement number: 197
#6942
Server -> Client
[FIN, ACK]
Sequence number 1689
Acknowledgement number: 197
#6951
Client -> Server
[ACK]
Sequence number 197
Acknowledgement number: 1690
Reference
FEATURED TAGS
algorithm
algorithmproblem
architecturalpattern
architecture
aws
c#
cachesystem
codis
compile
concurrentcontrol
database
dataformat
datastructure
debug
design
designpattern
distributedsystem
django
docker
domain
engineering
freebsd
git
golang
grafana
hackintosh
hadoop
hardware
hexo
http
hugo
ios
iot
java
javaee
javascript
kafka
kubernetes
linux
linuxcommand
linuxio
lock
macos
markdown
microservices
mysql
nas
network
networkprogramming
nginx
node.js
npm
oop
openwrt
operatingsystem
padavan
performance
programming
prometheus
protobuf
python
redis
router
security
shell
software testing
spring
sql
systemdesign
truenas
ubuntu
vmware
vpn
windows
wmware
wordpress
xml
zookeeper