【TCP/IP】TCP 断开实验

151 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情

一、前言

实验结论:

  • TCP 连接断开的挥手,在进程崩溃时,会由操作系统内核代劳
  • TCP 连接建立后,如果某一方断电或断网,如果此时刚好正在发送数据,TCP 数据包发送失败后会重试,重试达到上限时也会断开连接
  • TCP 连接建立后,如果某一方断电或断网,且这条连接没有数据传输时
    • 如果开启了 KeepAlive 则会在一定心跳检测后断开连接,这个默认检测时间大概2个多小时,比较久
    • 如果未开启 KeepAlive 则连接永远存在
  • 如果一方发送 RST 包给另一方,也是会强制对方断开连接的

先来看下 TCP 连接(三次握手)TCP 断开(四次挥手)

TCP 连接(三次握手)

在本地开启服务,端口 8080.

  1. 查看接口: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)
  1. 使用 tcpdump 抓包:
$ sudo tcpdump -A -vv -i any -S host 127.0.0.1
  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!

抓包输出如下:

2022-03-1817-16-39.png

  • [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

输出结果如下:

2022-03-1821-15-31.png



二、实验

问题:

  1. 断电/断网时,client 连接如何断开?
  2. 断电/断网后,server 重启再恢复又会如何?

带着这两个问题,来看下:

(1)断电/断网时,client 连接如何断开?

想想都知道,程序关闭,释放资源,当然会断开。

但程序意外或强制杀死了?进程突然被 kill -9 了呢?

实验步骤:

  1. 启动服务
  2. 启动 client 去连接服务
  3. tcpdump 抓包 client

会发现,进程异常终止,操作系统会帮忙断开连接(四次挥手)。

那断电/断网呢?连接不会立刻断开,因为 TCP 重传机制。


(2)断电/断网后,server 重启再恢复又会如何?

如果 clientserver 建立连接后,没有数据传输,断掉 server 端的网络,这时如果把 server 程序重启一下,再恢复网络,那这条连接还能用吗?

  • 如果 server 重启后,client 还是不发数据,那这条连接看起来还是可用的,因为他们根本不知道对方是个什么情况
  • 如果此时 client 发送一点数据给 server,你会发现 server 会发送一个 RSTclient,然后 client 就断开连接了