图解 TCP 四次挥手|深度解析|为什么是四次|为什么要等2MSL
写在前面
今天我们来图解一下TCP的四次挥手、深度解析为什么是四次?
上一片文章我们已经介绍了TCP的三次握手

解析四次挥手
数据传输完毕之后,通信的双方都可释放连接。现在客户端A和服务端B都处于ESTABLISHED状态。

第一次挥手
客户端A的应用进程先向TCP发出连接释放报文段,并停止再发送数据,主动关闭TCP连接。客户端A把链接释放报文段首部的终止控制位FIN置为1,其序号为seq=u,它等于前面以传送过的数据的最后一个字节的序号加1。这时候A进入了FIN-WAIT-1(终止等待1)状态,等待B的确认。
注意:TCP规定:FIN报文段即使不携带数据,也消耗掉一个序号!!

第二次挥手
服务端B收到链接释放报文段后即发出确认,确认号是ack = u + 1,而这个报文段自己的序号v是等于B前面已传送过的数据的最后一个字节的序号加1,然后B就进入CLOSE-WAIT(关闭等待)状态。

TCP服务器进程这时应通知应用进程,因而从A到B这个方向的链接就释放了。这时的TCP链接处于半关闭状态,即A已经没有数据要发送了,但B若发送数据,A仍要接收,也就是说,从B到A这个方向的连接并未关闭,这个状态要维持一段时间。
第三次挥手
A收到来自B的确认后,就进入了FIN-WAIT-2(终止等待2)状态满等待B发出的连接释放报文段。若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接,这时B发出的连接释放报文段必须使FIN = 1,现假定B的序号为w,B还必须重复上次已发送过的确认号ack = u + 1.这时B就进入LAST-ACK(最后确认)状态,等待A的确认。

第四次挥手
A在收到了B的链接释放报文段后,必须对此发出确认。在确认报文段中把ACK置1,确认号ack=w+1,而自己的序号是seq=u+1(根据TCP标准,前面发送过的FIN报文段要消耗一个序号),然后进入到TIME-WAIT(时间等待)状态。
注意: 现在TCP连接还没有还没有释放掉。必须经过时间等待计时器设置的时间2MSL后,A才能进入CLOSED状态。
MSL叫做最长报文段寿命,RFC793建议设在两分钟,但TCP允许不同的实现可以根据具体情况使用更小的MSL值。

为什么要2MSL时间呢
1. 为了保证A发送的最后一个ACK报文段能够到达B。
这个ACK报文段有可能丢失,因而使处于在LAST-ASK状态的B收不到对己发送的FIN-ACK报文段的确认。B会超时重传这个FIN+ACK报文段,而A就能在2MSL时间内收到这个重传的FIN+ACK报文段。接着A重传一次确认,重新启动2MSL计时器,最后的A和B都正常进入CLOSED状态。

如果A在TIME-WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,那么就无法收到B重传的FIN+ACK报文段,因而也不会再发送一次确认报文段。
2. 防止了已失效的连接请求报文段。
A 在发送完最后一个ACK报文段后,在经过时间2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,这样就可以使下一个连接中不会出现这种旧的连接请求报文段。B只要收到了A发出的确认,就进入CLOSED状态。同样,B在撤销相应的传输控制块TCB后,就结束了这次的TCP连接,所以B结束TCP连接的时间要比A早一些的。
为什么是四次?
首先我们可以确定一点TCP是全双工的,四次挥手是保证了双方都知道并且都已经断开连接。

四次挥手过程的目的是确保数据在关闭过程中能够被完整传输,同时也允许延迟的数据包在关闭后仍然能够被接收。TIME_WAIT 状态的存在是为了处理可能的重复数据包,以确保连接的完全关闭。
⚠️ 注意一点:关闭连接时,客户端A向服务端B发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。
问题又来了:为什么握手要三次,挥手却要四次呢?
服务器B收到客户端A的 FIN 报文时,先回一个 ACK 应答报文,而B可能还有数据需要处理和发送,等B不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。
握手的时候并没有数据传输,所以服务端的 SYN 和 ACK 报文可以一起发送,但是挥手的时候有数据在传输,服务端B通常需要等待完成数据的发送和处理, 所以服务端B的 ACK 和 FIN 一般都会分开发送,从而比三次握手导致多了一次。
参考
[1] https://segmentfault.com/a/1190000040571193
相关文章:
图解 TCP 四次挥手|深度解析|为什么是四次|为什么要等2MSL
写在前面 今天我们来图解一下TCP的四次挥手、深度解析为什么是四次? 上一片文章我们已经介绍了TCP的三次握手 解析四次挥手 数据传输完毕之后,通信的双方都可释放连接。现在客户端A和服务端B都处于ESTABLISHED状态。 第一次挥手 客户端A的应用进…...
DevExpress中文教程:如何将WinForms数据网格连接到ASP. NET Core WebAPI服务?
日前DevExpress官方发布了DevExpress WinForms的后续版本——将.NET桌面客户端连接到安全后端Web API服务(EF Core with OData),在本文中我们将进一步演示如何使用一个更简单的服务来设置DevExpress WinForms数据网格。 P.S:DevExpress WinForms拥有180…...
SpringBoot3核心特性-核心原理
目录 传送门前言一、事件和监听器1、生命周期监听2、事件触发时机 二、自动配置原理1、入门理解1.1、自动配置流程1.2、SPI机制1.3、功能开关 2、进阶理解2.1、 SpringBootApplication2.2、 完整启动加载流程 三、自定义starter1、业务代码2、基本抽取3、使用EnableXxx机制4、完…...
Linux:RPM软件包管理以及yum软件包仓库
挂载光驱设备 RPM软件包管理 RPM软件包简介 区分软件名和软件包名 软件名:firefox 软件包名:firefox-52.7.0-1.el7.centos.x86_64.rpm 查询软件信息 查询软件(参数为软件名) ]# rpm -qa #当前系统中所有已安装的软件包 ]# r…...
pod介绍与配置
1、pod概念介绍 Pod 是 kubernetes 基本调度单位。每个 Pod 中可以运 行一个或多个容器,共享 Pod 的文件系统、IP 和网络等资源,每个 Pod 只有一个 IP。 2、使用 yaml或json 文件创建 Pod 声明式文件方式创建 Pod,支持 yaml 和 json 1&…...
【Taro】初识 Taro
笔记来源:编程导航。 概述 Taro 官方文档:https://taro-docs.jd.com/docs/ (跨端开发框架) Taro 官方框架兼容的组件库: taro-ui:https://taro-ui.jd.com/#/ (最推荐,兼容性最好&…...
【设计模式-备忘录】
备忘录模式(Memento Pattern)是一种行为型设计模式,用于保存对象的内部状态,以便在将来某个时间可以恢复到该状态,而不暴露对象的内部实现细节。备忘录模式特别适合在需要支持撤销(Undo)操作的应…...
【数据结构】排序算法系列——快速排序(附源码+图解)
快速排序 接下来我们将要介绍的是排序中最为重要的算法之一——快速排序。 快速排序(英语:Quicksort),又称分区交换排序(partition-exchange sort),最早由东尼霍尔提出。快速排序通常明显比其…...
Arthas thread(查看当前JVM的线程堆栈信息)
文章目录 二、命令列表2.1 jvm相关命令2.1.2 thread(查看当前JVM的线程堆栈信息)举例1:展示[数字]线程的运行堆栈,命令:thread 线程ID举例2:找出当前阻塞其他线程的线程 二、命令列表 2.1 jvm相关命令 2.…...
Tomcat_WebApp
Tomcat的目录的介绍 /bin: 这个目录包含启动和关闭 Tomcat 的脚本。 startup.bat / startup.sh:用于启动 Tomcat(.bat 文件是 Windows 系统用的,.sh 文件是 Linux/Unix 系统用的)。shutdown.bat / shutdown.sh…...
代码随想录算法训练营Day10
150. 逆波兰表达式求值 力扣题目链接;. - 力扣(LeetCode) Collection——Deque——LInkedList类 class Solution {public int evalRPN(String[] tokens) {Deque<Integer> myquenew LinkedList<>();for(String a:tokens){if(a.…...
十个服务器中毒的常见特征及其检测方法
服务器作为企业的核心资源,其安全性至关重要。一旦服务器被病毒入侵,不仅会影响系统的正常运行,还可能导致数据泄露等严重后果。以下是十种常见的服务器中毒特征及其检测方法。 1. 系统性能下降 病毒常常占用大量的CPU和内存资源࿰…...
LeetCode 每周算法 6(图论、回溯)
LeetCode 每周算法 6(图论、回溯) 图论算法: class Solution: def dfs(self, grid: List[List[str]], r: int, c: int) -> None: """ 深度优先搜索函数,用于遍历并标记与当前位置(r, c)相连的所有陆地&…...
Selenium元素定位:深入探索与实践
目录 一、引言 二、Selenium元素定位基础 1. WebDriver与元素定位 2. 定位策略概览 三、ID定位 1. 特点与优势 2. 示例代码 四、Class Name定位 1. 特点与限制 2. 示例代码 五、XPath定位 1. 特点与优势 2. 示例代码 3. XPath高级用法 六、CSS Selector定位 1.…...
前端开发——(1)使用vercel进行网页开发
前端开发——(1)使用Vercel进行网页开发 在现代前端开发中,选择一个高效的部署平台至关重要。Vercel 提供了快速、简便的部署方式,特别适合静态网站和 Next.js 应用。本文将带你逐步了解如何使用 Vercel 部署并运行你的网页项目。…...
故障诊断│GWO-DBN灰狼算法优化深度置信网络故障诊断
1.引言 随着人工智能技术的快速发展,深度学习已经成为解决复杂问题的热门方法之一。深度置信网络(DBN)作为深度学习中应用比较广泛的一种算法,被广泛应用于分类和回归预测等问题中。然而,DBN的训练过程通常需要大量的…...
【工具】Windows|两款开源桌面窗口管理小工具Deskpins和WindowTop
总结 Deskpins 功能单一,拖到窗口上窗口就可以置顶并且标记钉子标签,大小 104 KB,开源位置:https://github.com/thewhitegrizzli/DeskPins/releases WindowTop 功能完善全面强大,包括透明度、置顶、选区置顶等一系列功…...
【Unity杂谈】iOS 18中文字体显示问题的调查
一、问题现象 最近苹果iOS 18系统正式版推送,周围升级系统的同事越来越多,有些同事发现,iOS 18上很多游戏(尤其是海外游戏)的中文版,显示的字很奇怪,就像一些字被“吞掉了”,无法显示…...
后端-navicat查找语句(单表与多表)
表格字段设置如图 语句: 1.输出 1.输出name和age列 SELECT name,age from student 1.2.全部输出 select * from student 2.where子语句 1.运算符: 等于 >大于 >大于等于 <小于 <小于等于 ! <>不等于 select * from stude…...
基于springboot的在线视频点播系统
文未可获取一份本项目的java源码和数据库参考。 国外研究现状: 与传统媒体不同的是,新媒体在理念和应用上都采用了新颖的媒介或媒体。新媒体是指应用在数字技术、在传统媒体基础上改造、或者更新换代而来的媒介或媒体。新兴媒体与传统媒体在理念和应用…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
