4个实验,彻底搞懂TCP连接的断开

结合Wireshark抓包实战,图文详解TCP三次握手及四次挥手原理(附下载) TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP是互联网核心协议之一,位于OSI模型的传输层,负责在互联网上的计算机之间提供可靠的数据传输服务。 阅读详情

前言

看到这个标题你可能会说,TCP 连接的建立与断开,这个我熟,不就是三次握手与四次挥手吗?且慢,脑海中可以先尝试回答这几个问题:

  • 四次挥手是谁发起的?
  • 如果断电/断网了连接会断开吗?
  • 什么情况下没有四次挥手连接也会断开?

这不是面试,而是遇到了实际问题,至于是什么问题,容我先卖个关子,本文也不会解答,后面会有一篇专门的文章来说遇到的问题是啥,所以在讲实际问题之前,先弄懂理论。

正常断开

我们由浅入深,先了解正常情况下 TCP 连接是如何断开的,下图为 TCP 三次握手与四次挥手的经典图(来自《TCP/IP详解卷1》)

在我们的电脑上,可以使用 python 的 SimpleHTTPServer 来快速起一个 http 服务(http 也是基于 TCP 协议),比如这样:

python -m SimpleHTTPServer 20880

再通过 nc 或 telnet 这两个命令来创建 TCP 连接,比如我测试使用 nc 来创建连接

nc -v ip port

Connection to ip port [tcp/*] succeeded! 表示连接成功

我们如何观察这个连接呢?可以通过 netstat 或 lsof 来查看这条"连接",这里我使用 lsof (mac 与 Linux 系统的 netstat 命令不太一样,使用起来有点别扭 )

lsof -i:20880

无论是客户端还是服务端都会占用一个端口,不过服务端端口是固定的,客户端端口是随机的。

如果我们想看 TCP 连接和断开时 握手 与 挥手 的 TCP 报文怎么查看呢?可以使用 tcpdump 命令

三次握手

tcpdump -A -vv -i any -S host 10.179.245.95

为了方便查看,和上面的经典图放在了一起

这里的参数需要提一下的是 -S ,如果不加 -S 参数看到的第三次握手的 ack=1 ,与书上的理论不太一样,其实这里只是 tcpdump 简化了展示,想看实际值需要加 -S

这里的 Flags [S]/[S.]/[.]

  • [S] 代表 SYN
  • [.] 代表 ACK,[S.] 就是 SYN + ACK

四次挥手

命令与抓三次握手相同,我们抓到如下挥手数据

  • [F] 代表 FIN

这张图有点奇怪,四次挥手居然变成了三次,这其实是 TCP 协议的实现问题,如果第二次与第三次挥手之间没有数据发送,那么被动断开连接的一方就可能会把第二次的 ACK 与 第三次的 FIN 合并为一次挥手。

当然我也抓到过正常的四次挥手,大概长这样

异常断开

上面铺垫了这么多,现在开始进入正题。

TCP 连接断开是谁发起的

我们来思考一个问题:TCP 连接的断开是谁发起的?程序本身还是操作系统?

我们来看一段非常简单的 TCP 连接创建与断开的代码

tcpAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:20880")
conn, err := net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
 fmt.Println("Client connect error ! " + err.Error())
 return
}

defer func() {
 err := conn.Close()
 fmt.Println("Client connect closed !")
 if err != nil {
  fmt.Println(err)
 }
}()

fmt.Println(conn.LocalAddr().String() + " : Client connected!")
time.Sleep(10 * time.Second)

运行后,效果如下,也符合我们预期:当程序打印 Client connected! 时,能看到连接,当打印 Client connect closed! 时,连接断开

如果我们在连接断开前使用 kill -9 强杀进程呢?(这里我用了两台电脑来测试)

我们发现 conn.Close() 并没有执行,但四次挥手还是发生了!

查阅资料发现如下结论:

a、b 两个正常连接的对端进程。假如 b 进程没有调用 close 就异常终止,那么发送 FIN 包是内核 OS 代劳

断电/断网时的连接是怎样断开的

我们通过上面的实验发现就算进程异常终止,操作系统也会帮忙发起四次挥手

但如果是断电或断网的情况下,操作系统就无法代劳了,这时会怎样呢?为了便于测试,这里用两台电脑,client 连接 server,断开 server 的网络来模拟断网断电情况。

可以肯定的是 断网,断电后,连接不会立即断开 ,那么后续连接是否会断开呢?我们分成下面几种情况来看

断网时有数据传输

断网时如果有数据发送,由于收不到 ACK,所以会重试,但并不会无限重试下去,达到一定的重发次数之后,如果仍然没有任何确认应答返回,就会判断为网络或者对端主机发生了异常,强制关闭连接。此时的关闭是直接关闭,而没有挥手(数据都发不出去,还挥啥手),Linux 下的设置为

最小重传时间是200ms 最大重传时间是120s 重传次数为15

断网时没有数据传输

断网时如果没有数据传输,还得看 TCP 连接的 KeepAlive 是否打开,关于 TCP 的 KeepAlive 简介如下:

  • TCP KeepAlive 是一种在不影响数据流内容的情况下探测对方的方式,采用 保活计时器 实现,当计时器被触发时,一端发送保活报文,另一端接收到报文后发送 ACK 响应
  • 它并不是 TCP 的规范,但大部分的实现都提供了这一机制
  • 该机制存在争议,有的人保活机制应该在应用程序中实现

开启KeepAlive

操作系统中有这么几个参数控制 KeepAlive 的配置:

  • Keepalive_time:空闲时间,即多长时间连接没有发送数据时开始 KeepAlive 检测
  • Keepalive_intvl:发送间隔时间,即上述代码的设置
  • Keepalive_probs:最多发送多少个检测数据包

在 Linux 上可以通过如下文件查看

cat /proc/sys/net/ipv4/tcp_keepalive_time
cat /proc/sys/net/ipv4/tcp_keepalive_intvl
cat /proc/sys/net/ipv4/tcp_keepalive_probes

如果按照这个默认值来看,得2小时没有数据传输,KeepAlive 才开始工作!

而在 Go 中只有两个参数可以设置:

conn.SetKeepAlive(true)
conn.SetKeepAlivePeriod(5 * time.Second)

其中第二个 SetKeepAlivePeriod 源码是这样的:

func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
 // The kernel expects seconds so round to next highest second.
 secs := int(roundDurationUp(d, time.Second))
 if err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, sysTCP_KEEPINTVL, secs); err != nil {
  return wrapSyscallError("setsockopt", err)
 }
 err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE, secs)
 runtime.KeepAlive(fd)
 return wrapSyscallError("setsockopt", err)
}

SetKeepAlivePeriod 的参数同时设置了 tcp_keepalive_intvl 和 tcp_keepalive_time,tcp_keepalive_probes 没法设置

做个简单测试:client 开启 KeepAlive 连接 server 后,什么数据都不发送,把server 的网断掉,可以看到 KeepAlive 心跳包,一段时间后连接被置为 CLOSED 状态

关闭KeepAlive

关闭 KeepAlive 后,如果没有数据传输,连接永远不会断开

断网后 server 重启再恢复

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

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

总结

除了正常情况之外,本文从 TCP 连接断开的角度结合实验给出了一些结论:

  • TCP 连接断开的 挥手 ,在进程崩溃时,会由操作系统内核代劳
  • 当 TCP 连接建立后,如果某一方断电或断网,如果此时刚好正在发送数据,TCP 数据包发送失败后会重试,重试达到上限时也会断开连接
  • 当 TCP 连接建立后,如果某一方断电或断网,且这条连接没有数据传输时
    • 如果开启了 KeepAlive 则会在一定心跳检测后断开连接,这个默认检测时间大概2个多小时,比较久
    • 如果未开启 KeepAlive 则连接永远存在
  • 如果一方发送 RST 包给另一方,也是会强制对方断开连接的
【3天快速入门WPF】8-数据绑定基础 以下是一个简单的 WPF 数据绑定示例,使用两个TextBox控件分别表示Name和Age来进行进行数据绑定试验。运行程序后,你会看到初始界面中TextBox 中显示初始名字 “张三”,TextBox 中显示初始年龄 “25”。在 XAML 中创建一个简单的界面,包含一个 TextBox 用于输入名字,一个 TextBox 用于显示年龄。当你在 TextBox 中修改名字时,Person 对象的 Name 属性会被自动更新,反之亦然。它的主要作用是为控件及其子控件提供一个默认的数据源,用于数据绑定。 阅读详情

相关推荐

反激电源RCD尖峰吸收电路的原理以及调试

反激电源RCD尖峰吸收电路的原理以及调试

mnmmnmn的博客 9255

net.ResolveTCPAddr(“tcp6“, address)

net.ResolveTCPAddr("tcp6", address)

PerfectUrl的博客 1187

Hyper-V集群部署指南

工欲善其事,必先利其器。搭建一个方便管理的服务集群,是分布式学习很重要的环境。 目前流行的虚拟机产品主要为Vmware 和 win10自带的Hyper-V(win10家庭版无此功能),网上关于Vmware的教程更多,显然它更容易上手,但Hyper-V也算是一个很不错的产品,这里记录一下我的学习过程: 目录 Hyper-V的安装 服务集群的搭建 虚拟机的网络通信 NAT网络的搭建 端口映射 Linux的静态IP 虚拟机的自启动问题 Hyper-V的安装 也不能算说是安装,如果你的win1

Swing 6923

Go中获取随机端口

在应用中使用随机端口启动应用是一个很常见的需求,尤其在微服务架构中做应用负载均衡时尤为常见。在 Golang 中生成随机端口相对比较容易,我们可以通过使用net 包中的方法就能很快实现。具体实现如下所述。 一、实现原理 主要使用 net 包中的的以下两个方法: 1. ResolveTCPAddr func ResolveTCPAddr(net, addr string) (*TCPAddr, error) ResolveTCPAddr 能将 addr 作为TCP 地址解析并返回 参数addr.

zmqzhy的专栏 2003

ComfyUI+minimaxh3本地部署:漫剧分镜批量生成工作流全实操

视频生成模型正从云端API向本地化部署迁移,背后的技术逻辑是将扩散模型的文本编码、潜空间采样、VAE解码等阶段拆分为可编排的独立环节。ComfyUI作为节点化管线工具,恰好能以可视化连线方式管理这些阶段,让生成过程可控、可复用、可批量执行。minimaxh3模型支持本地推理,配合LoRA微调与参数优化,能够在保证角色一致性的前提下,从分镜脚本批量产出连续剧情片段,规避云端排队、成本高、素材不可控等工程问题。这套工作流广泛应用于漫剧、短剧和动态条漫的工业化生产,尤其适合需要高频迭代分镜草稿的内容团队。文本以零

weixin_29057065的博客 367

【文章阅读+代码复现】Point-GNN

Brief 在3D点云语义分割方法中,GNN已经做了很多可用的方案,但是在目标检测上依旧是采用比较传统的CNN和稀疏卷积的组合,这一篇文章是研究了图卷积在3D检测的中的用法。来自卡内基梅隆大学。已经被CVPR2020接收. 这里是 paper 这里是 code Abstruct 一个采用GNN设计的3D目标检测框架 过程是先将点云场景编码成图结构,随后设计了一个叫point-GNN的网络结构,在...

有所为,有所成长 1万+

go基础-19.网络编程

go网络编程

枫枫知道的个人博客 487

深入解析BLheli电调固件与Dshot通讯协议:从原理到实践

本文深入解析了无人机动力系统的核心——BLheli电调固件与Dshot通讯协议。详细阐述了BLheli固件从经典版到BLheli_32的演进及其功能特性,并重点剖析了Dshot数字协议如何通过数据包和校验码实现更快、更准、更可靠的电机控制。文章还涵盖了双向Dshot遥测、实战配置与调参指南,帮助玩家充分释放无人机性能。

weixin_28273593的博客 437

Go tcp客户端、服务端编程

内容参考net包,net包提供了可移植的网络I/O接口,包括TCP/IP、UDP、域名解析和Unix域socket。 虽然本包提供了对网络原语的访问,大部分使用者只需要Dial、Listen和Accept函数提供的基本接口;以及相关的Conn和Listener接口。crypto/tls包提供了相同的接口和类似的Dial和Listen函数。 服务端 在服务器端我们需要绑定服务到指定的非激活端口, 并监听此端口;当有客户端请求到达的时候可以接收到来自客户端连接的请求。 package main

hellozhxy的博客 1005

如何使用Qt的PIMPL习惯用法(PIMPL Idiom

PIMPL是指“Pointer to IMPLementation”(指向实现的指针),意味着将实现细节隐藏起来,用户类无需关注这些实现细节。在Qt中常用PIMPL习惯用法来清晰地区分接口与实现,尽管Qt官方文档并未详细说明该机制。本文将演示如何在Qt中使用PIMPL习惯用法,并以一个简单的坐标输入对话框作为实例。

电脑管家 1035

告别CANoe?手把手教你用Python+PCAN搭建汽车诊断脚本(附完整代码)

本文详细介绍了如何利用Python和PCAN硬件搭建高性价比的汽车诊断自动化方案,替代昂贵的CANoe工具。通过开源库python-can和udsoncan实现UDS诊断协议,涵盖硬件选择、环境配置、核心功能实现及性能优化,附完整代码示例,助力开发者快速构建诊断脚本。

weixin_42551227的博客 373

牛批!4个实验,彻底搞懂TCP连接的断开

前言 看到这个标题你可能会说,TCP 连接的建立与断开,这个我熟,不就是三次握手与四次挥手嘛。且慢,脑海中可以先尝试回答这几个问题: 四次挥手是谁发起的? 如果断电/断网了连接会断开吗? 什么情况下没有四次挥手连接也会断开? 这不是面试,而是遇到了实际问题,至于是什么问题,容我先卖个关子,本文也不会解答,后面会有一篇专门的文章来说遇到的问题是啥,所以在讲实际问题之前,先弄懂理论。 正常断开 我们由浅入深,先了解正常情况下 TCP 连接是如何断开的,下图为 TCP 三次握手与四次挥手的经典图(来自《TCP

weixin_48791363的博客 620

YoloV8优化:感受野注意力卷积运算(RFAConv),效果秒杀CBAM和CA等 | 即插即用系列

感受野注意力卷积运算(RFAConv),解决卷积块注意力模块(CBAM)和协调注意力模块(CA)只关注空间特征,不能完全解决卷积核参数共享的问题

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 4266

4个实验,彻底搞懂TCP连接的断开,大厂Java开发面试解答

这份《“java高分面试指南”-25分类227页1000+题50w+字解析》同样可分享给有需要的朋友,感兴趣的伙伴们可挑战一下自我,在不看答案解析的情况,测试测试自己的解题水平,这样也能达到事半功倍的效果!(好东西要大家一起看才香)作为过来人,小编是整理了很多进阶架构视频资料、面试文档以及PDF的学习资料,针对上面一套系统大纲小编也有对应的相关进阶架构视频资料网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

2401_84433658的博客 948

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

最新4个实验,彻底搞懂TCP连接的断开,大厂Java开发面试解答(1),java线程池原理面试

做任何事情都要用心,要非常关注细节。看起来不起眼的、繁琐的工作做透了会有意想不到的价值。当然要想成为一个技术大牛也需要一定的思想格局,思想决定未来你要往哪个方向去走, 建议多看一些人生规划方面的书籍,多学习名人的思想格局,未来你的路会走的更远。更多的技术点思维导图我已经做了一个整理,涵盖了当下互联网最流行99%的技术点,在这里我将这份导图分享出来,以及为金九银十准备的一整套面试体系,上到集合,下到分布式微服务本文已被。

weixin_43747371的博客 871

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

一文搞懂TCP的三次握手和四次挥手

一文搞懂TCP的三次握手和四次挥手

不脱发的程序猿 19万+

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

3 万字 + 100 张图带你彻底搞懂 TCP 面试题(强烈建议收藏)

大家好,我是小林,一个专为大家图解的工具人。 不管面试 Java 、C/C++、Python 等开发岗位, TCP 的知识点可以说是必问的了。 任 TCP 虐我千百遍,我仍待 TCP 如初恋。 过去不会没关系,今天就让我们来消除这份恐惧,微笑着勇敢的面对它吧! 所以小林整理了关于 TCP 的面试题型,全文共 3 万字 + 100 张图,跟大家一起探讨探讨。 1、 TCP 基本认识 2、TCP 连接建立 3、 TCP 连接断开 4、 Socket 编程 5、TCP 重传、滑动窗口、流量控制、拥塞控制

小林coding 1万+

两张图片轻松搞懂TCP连接时的三次握手以及断开连接时的四次挥手——面试高频

我们先来看一张图片简单了解一下TCP在请求中是为什么要进行三次“对话”

qishuang6的博客 1205
上一篇: 如何将jdk12的源码导入idea
下一篇: 8种有效方式迭代Java Map中的每个条目
JavaMonsterr
博客等级 码龄4年 211粉丝 481原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值