【网络面积篇】TCP断开连接(笔记)
目录
一. 四次挥手
(1)过程描述
(2)为什么是四次挥手?
二、相关问题
1. 第一次挥手丢失了,会发生什么?
2. 第二次挥手丢失了,会发生什么?
补充:close 函数 和 shutdown 函数的不同
3. 第三次挥手丢失了,会发生什么?
4. 第四次挥手丢失了,会发生什么?
5. 为什么需要 TIME_WAIT 状态?
(1)防止历史连接中的数据,被后面相同四元组的连接错误的接收
(2)保证「被动关闭连接」的一方,能被正确的关闭
6. 什么情况会出现三次挥手?
什么是 TCP 延迟确认机制?
一. 四次挥手
双方 都可以 主动断开 连接,断开连接后 主机中的「资源」将被释放。
(1)过程描述
- ① 客户端 打算 关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。
- ② 服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSE_WAIT 状态。
- ③ 客户端 收到 服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。
- ④ 等待 服务端 处理完数据后,也向 客户端 发送 FIN 报文,之后 服务端 进入 LAST_ACK 状态。
- ⑤ 客户端 收到 服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态。
- ⑥ 服务端收到了 ACK 应答报文后,就进入了 CLOSE 状态,至此 服务端已经 完成连接的关 闭。
- ⑦ 客户端在经过 2MSL 一段时间后,自动进入 CLOSE 状态,至此 客户端 也完成 连接的关闭。
这里 每个方向 都需要一个 FIN 和 一个 ACK,因此 通常被 称为 四次挥手。这里一点 需要注意是:主动关闭连接的,才有 TIME_WAIT 状态。
(2)为什么是四次挥手?
- 关闭 连接时,客户端 向 服务端 发送 FIN 时,仅仅 表示客户端 不再发送 数据了 但是还能 接收数据。
- 服务端 收到 客户端的 FIN 报文时,先回一个 ACK 应答报文,而 服务端 可能 还有 数据需要处理 和 发送,等 服务端 不再发送数据 时,才发送 FIN 报文 给客户端 来表示 同意现在 关闭连接。
从 上面过程 可知,服务端 通常需要 等待完成 数据的 发送和处理,所以 服务端 的开发送,因此是 需要 四次挥手。ACK 和 FIN 一般 都会 分开发送,因此是 需要 四次挥手。
二、相关问题
1. 第一次挥手丢失了,会发生什么?
当客户端(主动关闭方)调用 close 函数后,就会向服务端发送 FIN 报文,试图与服务端断开连接,此时客户端的连接进入到 FIN_WAIT_1状态。正常情况下,如果 能 及时 收到服务端(被动 关闭方)的 ACK,则会很快变为 FIN_WAIT_2 状态。
如果 第一次挥手 丢失了,那么 客户端迟迟 收不到 被动方的 ACK 的话,也就会 触发 超时重传机制,重传 FIN 报文,重发次数由 tcp_orphan_retries 参数 控制。当客户端重传 FIN 报文的次数超过 tcp_orphan_retries 后,就不再发送 FIN 报文,则会在等待一段时间(时间为上一次超时时间的 2 倍),如果 还是没能 收到 第二次挥手,那么 直接进入到 close 状态。
举个例子,假设 tcp_orphan_retries 参数值 3,当 第一次挥手一直 丢失时,发生的 过程如下图:
当客户端 超时重传 3 次 FIN 报文后,由于 tcp_orphan_retries 为 3,已 达到 最大重传 次数,于是 再等待一段时间(时间为 上一次 超时时间的 2 倍),如果 还是没能 收到 服务端的 第二次 挥手(ACK 报文),那么 客户端就会 断开连接。
2. 第二次挥手丢失了,会发生什么?
当服务端 收到客户端的 第一次挥手后,就会先回一个 ACK 确认 报文,此时 服务端 的 连接进入到 CLOSE_WAIT 状态。
ACK 报文是不会重传的,所以 如果 服务端的 第二次挥手 丢失了,客户端 就会 触发超时重传机制,重传 FIN 报文,直到 收到 服务端的 第二次挥手,或者 达到最大的 重传次数。
举个例子,假设 tcp_orphan_retries 参数值 2,当 第二次挥手 一直丢失 时,发生的 过程如下图:
当客户端 超时重传 2 次 FIN 报文后,由于 tcp_orphan_retries 为 2,已达到 最大重传次数,于是再 等待一段时间(时间为 上一次 超时时间的 2 倍),如果 还是没能 收到 服务端 的 第二次挥手(ACK 报文),那么 客户端 就会 断开连接。
补充:close 函数 和 shutdown 函数的不同
当 客户端 收到 第二次挥手,也就是 收到服务端 发送的 ACK 报文后,客户端 就会处于 FIN_WAIT_2 状态,在 这个状态 需要 等服务端 发送 第三次挥手,也就是 服务端的 FIN 报文。
对于 close 函数关闭的 连接,由于 无法再 发送 和 接收数据,所以 FIN_WAIT_2 状态 不可以 持续太久,而 tcp_fin_timeout 控制了 这个状态下 连接的 持续时长,默认值是 60 秒。
这 意味着 对于 调用 close 关闭的 连接,如果在 60 秒 后还 没有收到 FIN 报文,客户端(主动关闭方)的连接就会 直接关闭,如下图:
如果 主动关闭方 使用 shutdown 函数 关闭连接,指定了 只关闭 发送方向,而 接收方向 并没有 关闭,那么 意味着 主动关闭方 还是 可以 接收数据的。此时,如果 主动关闭方 一直没 收到 第三次挥手,那么 主动关闭方的 连接 将会一直 处于 FIN_WAIT_2 状态(tcp_fin_timeout 无法控制 shutdown 关闭的连接)。如下图:
3. 第三次挥手丢失了,会发生什么?
当 服务端(被动关闭方)收到 客户端(主动关闭方)的 FIN 报文后,内核会 自动回复 ACK,同时 连接处于 CLOSE_WAIT 状态,顾名思义,它表示 等待 应用进程 调用 close 函数 关闭连接。此时,内核 是 没有权利 替代 进程 关闭连接,必须 由进程 主动 调用 close 函数来 触发 服务端 发送 FIN 报文。
服务端 处于 CLOSE_WAIT 状态时,调用了 close 函数,内核 就会 发出 FIN 报文,同时 连接进入LAST_ACK 状态,等待 客户端 返回 ACK 来 确认连接 关闭。如果 迟迟 收不到这个 ACK,服务端就会重发 FIN 报文,重发次数 仍然 由 tcp_orphan_retries 参数 控制,这与 客户端 重发 FIN 报文的 重传次数 控制方式是 一样的。
举个例子,假设 tcp_orphan_retries = 3,当 第三次挥手 一直丢失 时,发生的 过程如下图:
- 当服务端 重传 第三次挥手 报文的 次数达到了 3 次 后,由于 tcp_orphan_retries 为 3,达到了 重传 最大次数,于是 再等待 一段时间(时间为 上一次 超时时间的 2 倍),如果 还是 没能 收到客户端的 第四次挥手(ACK 报文),那么 服务端 就会 断开连接。
- 客户端 因为是 通过 close 函数 关闭连接的,处于 FIN_WAIT_2 状态是 有时长 限制的,如果tcp_fin_timeout 时间内 还是没能 收到服务端的 第三次挥手(FIN 报文),那么 客户端就会 断开连接。
4. 第四次挥手丢失了,会发生什么?
当 客户端 收到服务端的 第三次挥手的 FIN 报文后,就会 回 ACK 报文,也就是 第四次挥手,此时 客户端 连接 进入 TIME_WAIT 状态。
在 Linux 系统,TIME_WAIT 状态 会持续 2MSL 后才会 进入 关闭状态。然后,服务端(被动关闭方)没有收到 ACK 报文前,还是处于 LAST_ACK 状态。如果 第四次挥手 的 ACK 报文 没有 到达服务端,服务端 就会 重发 FIN 报文,重发次数 仍然由 tcp_orphan_retries 参数 控制。
举个例子,假设tcp_orphan_retries 为 2,当 第四次挥手 一直丢失时,发生的过程如下:
- 当 服务端 重传 第三次挥手 报文达到 2 时,由于 tcp_orphan_retries 为 2,达到了 最大重传次数,于是 再等待一段时间(时间为 上一次 超时时间的 2 倍),如果 还是没能 收到 客户端的 第四次挥手(ACK 报文),那么 服务端 就会 断开连接。
- 客户端 在收到 第三次挥手后,就会进入 TIME_WAIT 状态,开启 时长为 2MSL 的定时器,如果途中 再次 收到 第三次挥手(FIN 报文)后,就会 重置定时器,当 等待 2MSL 时长后,客户端 就会断开连接。
5. 为什么需要 TIME_WAIT 状态?
(1)防止历史连接中的数据,被后面相同四元组的连接错误的接收
先来了解序列号(SEQ)和初始序列号(ISN):
- 序列号,是 TCP 一个 头部字段,标识了 TCP 发送端 到 TCP 接收端的 数据流的 一个字节,因为TCP 是 面向字节流的 可靠协议,为了 保证消息的 顺序性和可靠性,TCP 为 每个传输方向上的 每个字节 都 赋予了一个 编号,以 便于 传输成功后 确认、丢失 后重传 以及在 接收端保证 不会乱序。序列号是一个 32 位的 无符号数,因此 在到达 4G 之后 再循环回到 0。
- 初始 序列号,在 TCP 建立连接的 时候,客户端和服务端 都会 各自生成一个 初始序列号,它是 基于 时钟生成的 一个 随机数,来 保证 每个连接 都拥有 不同的 初始序列号。初始化 序列号 可被视为 一个 32 位的 计数器,该 计数器 的数值 每 4 微秒 加 1,循环 一次需要 4.55 小时。
序列号和初始化 序列号 并不是 无限递增的,会 发生 回绕为 初始值的 情况,这意味着 无法 根据序列号来 判断 新老数据。
假设 TIME-WAIT 没有等待时间或时间过短,被延迟的数据包抵达后会发生什么呢?
- 服务端 在 关闭连接 之前 发送的 SEQ =301 报文,被 网络 延迟了。
- 接着,服务端 以相同的 四元组 重新打开了 新连接,前面 被延迟的 SEQ=301 这时 抵达了 客户端,而且 该数据报文的 序列号 刚好在 客户端 接收窗口内,因此 客户端会 正常接收 这个 数据报文,但是 这个数据报文是 上一个 连接残留下来 的,这样就 产生 数据错乱 等 严重的问题。
为了 防止历史 连接中的 数据,被 后面 相同四元组的 连接错误的 接收,因此 TCP 设计了 TIME_WAIT 状态,状态 会 持续 2MSL 时长,这个 时间 足以让 两个方向上的 数据包都 被丢弃,使得 原来 连接的 数据包 在网络中 都 自然消失,再 出现的 数据包 一定都是 新建立 连接 所产生的。
(2)保证「被动关闭连接」的一方,能被正确的关闭
TIME-WAIT 作用是 等待足够的时间 以确保 最后的 ACK 能让 被动关闭方 接收,从而 帮助其 正常关闭。
如果 客户端(主动关闭方)最后一次 ACK 报文(第四次挥手)在 网络中 丢失了,那么 按照 TCP 可靠性原则,服务端(被动关闭方)会 重发 FIN 报文。
假设 客户端 没有 TIME_WAIT 状态,而是在 发完 最后一次 回 ACK 报文就 直接进入 CLOSE 状态,如果该 ACK 报文 丢失了,服务端 则 重传的 FIN 报文,而这时 客户端 已经 进入到 关闭状态了,在 收到服务端 重传的 FIN 报文后,就会回 RST 报文。
服务端 收到 这个 RST 并将其 解释为一个 错误(Connection reset by peer),这对于 一个 可靠的协议 来说 不是一个 优雅的 终止方式。为了 防止这种 情况出现,客户端 必须 等待足够长的 时间,确保 服务端 能够收到 ACK,如果 服务端 没有 收到 ACK,那么 就会触发 TCP 重传机制,服务端会 重新 发送一个 FIN,这样 一去一来 刚好 两个 MSL 的时间。
客户端在 收到 服务端 重传的 FIN 报文时,TIME_WAIT 状态的 等待时间,会重置回 2MSL。
6. 什么情况会出现三次挥手?
当 被动 关闭方(上图的 服务端)在 TCP 挥手过程中,「没有数据要发送」并且「开启了 TCP 延迟确认机制」,那么 第二 和 第三次 挥手 就会 合并传输,这样就 出现了 三次挥手。(TCP 延迟确认机 制 默认开启)
什么是 TCP 延迟确认机制?
当 发送 没有携带 数据的 ACK,它的 网络效率 也是 很低的,因为 它也有 40 个字节的 IP 头 和TCP 头,但却 没有 携带 数据报文(浪费)。
为了解决 ACK 传输效率低 问题,所以就 衍生出了 TCP 延迟确认。TCP 延迟确认的策略:
- 当 有响应数据 要发送 时,ACK 会 随着 响应数据 一起 立刻 发送给对方。
- 当 没有 响应数据 要发送时,ACK 将会 延迟 一段时间,以 等待 是否有 响应 数据 可以一起 发送。
- 如果 在 延迟等待 发送 ACK 期间,对方的 第二个 数据报文 又到达了,这时 就会 立刻发送 ACK。
相关文章:

【网络面积篇】TCP断开连接(笔记)
目录 一. 四次挥手 (1)过程描述 (2)为什么是四次挥手? 二、相关问题 1. 第一次挥手丢失了,会发生什么? 2. 第二次挥手丢失了,会发生什么? 补充:close …...

下跌多少才能涨回来?
文章目录 上涨下跌函数关系函数图形数学分析 上涨下跌函数关系 最近炒股很热,对于股票来说,有个很重要的参数涨跌幅,那么下跌多少才能涨回来?这个不需要太深的知识就可以计算出来,下跌和上涨不是等价的,下跌…...

【AAOS】【源码分析】CarSystemUI -- CarSystemBar
CarSystemBar不像Android手机那样固定的顶部“状态栏”和底部“导航栏”,而是将StatusBar和NavigationBar都统称为SystemBar,可以通过如下配置为每侧最多配置一个“系统栏”。 packages/apps/Car/SystemUI/res/values/config.xml<!-- Configure which system bars should …...
[供应链] 邀请招标
1.邀请招标定义 邀请招标(Invitation to Bid by Request) 也称为有限竞争性招标(limited Competitive Bidding)或选择性招标(Selected Bidding) 邀请招标的采购方式下,采购人(如政府机构、企业或其他组织)不是公开发布招标信息,而是根据供应商或承包商…...

VS2017+Qt5.12.9+CMake3.30.2编译VTK 9.2.0
一.准备工作 vs2017,QT,Cmake自行下载准备, VTK下载地址 1.官网下载 2.github下载 二.编译VTK源码 1.个人习惯创建以下目录,一个源码目录,Build为vs解决方案输出目录和编译输出以及中间生成文件目录 2.cmake基础…...
Java线程CPU占用过高如何排查?
使用ps命令查看java进程详细信息: ps aux | grep java使用top命令查看系统进程占用情况 top使用jstack命令导出Java进程的堆栈信息 jstack pid | grep tid -A 10 "java.lang.Thread.State" > gc.log找出占用cpu最高的线程id: top -Hp -d 1 …...

uniapp推送配置流程
Dcloud Dcloud注册账号 个推 了解即可 注册个推账号 ios配置流程 需配置含有推送的描述文件以及p8证书 配置推送证书 ios证书配置报技术错误(参数错误) TeamID-苹果开发者账号唯一的ID 安卓需配置多厂商 小米手机需要配置小米厂商 华为手机则需…...

qt QPicture详解
1、概述 QPicture类是Qt框架中的一个重要图形类,它主要用于记录和回放QPainter的绘图指令。这个类能够跨平台、无分辨率依赖地绘制图形,非常适合用于实现打印预览和图像操作等场景。QPicture可以将绘图操作序列化为一种独立于平台的格式,保存…...
ScheduledFuture Source Code Analysis
ScheduledFuture Overview is a delayed result-bearing action, 可以被cancel.通常是在ScheduledExecutorService里面schedule一个task, 然后ScheduledFuture是其task执行接受后的返回结果。 Code Analysis 继承于两个接口: extends Delayed, Future一些继承ch…...

【CSS】CSS 样式重置 (normalize.css 和 reset.css) 和通用样式配置
一般来说,每一个项目初始化阶段都需要样式重置和样式定制化。样式重置最常用的就是 normalize.css 和 reset.css 这两个文件。 他们的区别: Normalize.css更加注重保留有用的浏览器默认样式,仅修复浏览器之间的不一致性,适用于需…...
自动化机器学习(AutoML)详解
自动化机器学习(AutoML)详解 引言 在数据驱动的时代,将庞大的数据集转化为有价值的洞察和预测模型是众多组织的首要任务。然而,传统的机器学习流程复杂且耗时,包括数据预处理、特征选择、模型选择、调参以及模型评估…...
Linux: network:erspan0
文章目录 问题介绍生成时间:代码Linux引入后面NONE是怎么生成的问题 最近看到一个网卡是erspan0,不知道是做什么用的: # ip -d link show erspan0 7: erspan0@NONE: <BROADCAST,MULTICAST> mtu 1450 qdisc noop state DOWN mode DEFAULT group default qlen 10000...

第11课 计算思维
从二级考试开始,计算思维基本上以编程题的形式考察。为了避免一看就会,一写就废的情况,需要我们加强编程练习,把学到的知识,通过实战练习,变成自己的本领。 同一道题,一般会有多种解决方法&…...
ACL, ACL Workshop, ACL Findings 解释
ACL(Annual Conference of the Association for Computational Linguistics)是自然语言处理(NLP)领域的顶级会议之一,但确实有多个与ACL相关的会议和出版物,具体如下: ACL Main Conference&…...

《使用Gin框架构建分布式应用》阅读笔记:p272-p306
《用Gin框架构建分布式应用》学习第15天,p272-p306总结,总35页。 一、技术总结 1.TDD(test-driven development) 虽然经常看到TDD这个属于,从本人的工作经历看,实际开发中用得相对较少。 2.unitest(单元测试) go语言开发中&a…...

【搜索引擎】俄罗斯搜索引擎yandex
俄罗斯搜索引擎yandex 1997年,俄罗斯搜索引擎Yandex(俄语意为:语言目录)首次上线,已发展成为全球第四大搜索引擎和第二大非英语搜索引擎 https://yandex.com/...

加密源代码|html代码如何加密保护?3分钟学会4种源代码加密妙招,代码人必看
你是否曾担心过自己的源代码被轻易复制或篡改? 在这个开源和共享盛行的时代,如何加密源代码,成为了每个开发者不得不面对的问题。 古人云:“工欲善其事,必先利其器。”今天,我们就来探讨一下如何加密保护你…...
Jetson Orin NX平台自研载板 IMX477相机掉线问题调试记录
1. 前言 平台: NVIDIA Orin NX 硬件: 自研载板 相机: 3个IMX477树莓派HQ摄像头通过CSI接口连接 版本: L4T 35.4.1(我们也在35.5.0上测试了一些东西) 参数: 30fps,4032x3040 问题描述: 其中一个IMX477相机在录制过程中出现可变时间后退出 短则10秒,长则5小时,…...
spring-boot(整合mybatisplus、及常见注解)
介绍 在日常开发中单表的CRUD功能代码重复度很高,也没有什么难度。而这部分代码量往往比较大,开发起来比较费时。 目前企业中都会使用一些组件来简化或省略单表的CRUD开发工作。目前在国内使用较多的一个组件就是MybatisPlus. MyBatisPlus是针对于Mybatis框架的增强,即合…...

深度学习:yolov3的使用--建立模型
使用argparse模块来定义和解析命令行参数 创建一个ArgumentParser对象 parser argparse.ArgumentParser() 训练的轮数,每批图像的大小,更新模型参数之前累积梯度的次数,模型定义文件的路径。 parser.add_argument("--epochs", typeint, d…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...