持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情
一、前言
实验结论:
TCP
连接断开的挥手,在进程崩溃时,会由操作系统内核代劳- 当
TCP
连接建立后,如果某一方断电或断网,如果此时刚好正在发送数据,TCP
数据包发送失败后会重试,重试达到上限时也会断开连接 - 当
TCP
连接建立后,如果某一方断电或断网,且这条连接没有数据传输时- 如果开启了
KeepAlive
则会在一定心跳检测后断开连接,这个默认检测时间大概2个多小时,比较久 - 如果未开启
KeepAlive
则连接永远存在
- 如果开启了
- 如果一方发送
RST
包给另一方,也是会强制对方断开连接的
先来看下 TCP
连接(三次握手) 和 TCP
断开(四次挥手)。
TCP
连接(三次握手)
在本地开启服务,端口 8080.
- 查看接口:
lsof -i:8080
$ lsof -i:8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 902 donald 141u IPv6 564055 0t0 TCP *:http-alt (LISTEN)
java 902 donald 151u IPv6 574494 0t0 TCP localhost:http-alt->localhost:43254 (ESTABLISHED)
nc 1009 donald 3u IPv4 569733 0t0 TCP localhost:43254->localhost:http-alt (ESTABLISHED)
- 使用
tcpdump
抓包:
$ sudo tcpdump -A -vv -i any -S host 127.0.0.1
- 连接本地服务:
nc -v 127.0.0.1 8080
$ nc -v 127.0.0.1 8080
Connection to 127.0.0.1 8080 port [tcp/http-alt] succeeded!
抓包输出如下:
[S]
代表SYN
[.]
代表ACK
[S.]
就是SYN + ACK
TCP
断开(四次挥手)
连接本地服务:nc -v 127.0.0.1 8080
,并断开 CTRL + C
$ nc -v 127.0.0.1 8080
Connection to 127.0.0.1 8080 port [tcp/http-alt] succeeded!
^C
输出结果如下:
二、实验
问题:
- 断电/断网时,
client
连接如何断开? - 断电/断网后,
server
重启再恢复又会如何?
带着这两个问题,来看下:
(1)断电/断网时,client
连接如何断开?
想想都知道,程序关闭,释放资源,当然会断开。
但程序意外或强制杀死了?进程突然被 kill -9
了呢?
实验步骤:
- 启动服务
- 启动
client
去连接服务 tcpdump
抓包client
会发现,进程异常终止,操作系统会帮忙断开连接(四次挥手)。
那断电/断网呢?连接不会立刻断开,因为 TCP
重传机制。
(2)断电/断网后,server
重启再恢复又会如何?
如果 client
与 server
建立连接后,没有数据传输,断掉 server
端的网络,这时如果把 server
程序重启一下,再恢复网络,那这条连接还能用吗?
- 如果
server
重启后,client
还是不发数据,那这条连接看起来还是可用的,因为他们根本不知道对方是个什么情况 - 如果此时
client
发送一点数据给server
,你会发现server
会发送一个RST
给client
,然后client
就断开连接了