TCP 建链(三次握手)和断链(四次握手)
TCP 建链(三次握手)和断链(四次挥手)
- 背景
- 简介
- 建链(三次握手)
- 断链(四次挥手)
- 序号及标志位
- 延伸问题
- 为什么建立连接需要握手三次,两次行不行?
- 三次握手可以携带数据吗?
- 为什么释放连接是四次,比建立连接多一次?
- 为什么 `TIME_WAIT` 状态需要经过 `2MSL` 才能返回到 `CLOSED` 状态?
背景
随着年龄的增长,很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来,技术出身的人总是很难放下一些执念,遂将这些知识整理成文,以纪念曾经努力学习奋斗的日子。本文内容并非完全原创,大多是参考其他文章资料整理所得,感谢每位技术人的开源精神。
简介
本文介绍 TCP 的建链和断链过程,即通常所说的三次握手和四次挥手的过程。
建链(三次握手)
TCP 建链需要客户端与服务器之间交互 3 个数据包,主要作用就是为了确认双方的接收和发送能力是否正常,初始序列号、交换窗口大小以及 MSS 等信息。
-
第一次握手
客户端发送请求连接数据包到服务器,标志位SYN
置为1
,随机生成一个初始序号seq
,即SYN=1 seq=x
,客户端从CLOSED
状态进入SYN_SENT
状态,等待服务器回复。 -
第二次握手
服务器收到请求数据包后根据标志位SYN=1
知道客户端在请求建立连接,服务器将标志位SYN
和ACK
都置为1
,确认序号ack=x+1
,随机生成一个初始序号seq=y
,并将该数据包SYN=1, ACK=1, seq=y, ack=x+1
回复给客户端确认连接请求,服务器从LISTEN
状态进入SYN_RCVD
状态。 -
第三次握手
客户端收到确认后检查确认序号ack
是否为x+1
,ACK
是否为1
,如果正确则将标志位ACK
置为1,确认序号ack=y+1
,并将该数据包ACK=1, seq=x+1, ack=y+1
发送给服务器,发送完成后客户端进入ESTABLISHED
状态,服务器接收到后检查确认序号ack
是否为y+1
,如果正确则连接建立成功,服务器进入ESTABLISHED
状态。随后客户端与服务器间可以开始传输数据。
断链(四次挥手)
-
第一次挥手
客户端发起FIN
包FIN=1, ACK=1, seq=u, ack=v
,客户端从ESTABLISHED
状态进入FIN_WAIT_1
状态。TCP 协议规定,即使FIN
包不携带数据,也要消耗一个序号。此FIN
包中ACK=1
和ack=v
基于断链前正常通信的数据包。 -
第二次挥手
服务器收到FIN
包,发出ACK
确认包,并带上自己的序号seq=v
(ACK=1 seq=v ack=u+1
),服务器进入从ESTABLISHED
状态进入CLOSE_WAIT
状态。此时客户端已经没有数据需要发送给服务器了,但服务器如果仍有数据发送给客户端的话,客户端依然需要接收。客户端接收到服务器发送的ACK
后进入FIN_WAIT_2
状态。 -
第三次挥手
服务器数据发送完成后向客户端发送FIN
包FIN=1, ACK=1, seq=w, ack=u+1
,半连接状态下服务器可能又发送了一些数据,假设发送seq
为w
,服务器进入LAST_ACK
状态。 -
第四次挥手
客户端接收到服务器的FIN
包后发出确认包ACK=1, seq=u+1, ack=w+1
,客户端进入TIME_WAIT
状态,此时 TCP 连接还没有释放,必须经过2*MSL
后才进入CLOSED
状态,而服务器接收到客户端的ACK
后就进入了CLOSED
状态,服务器结束 TCP 连接的时间要比客户端早一些。
序号及标志位
TCP 建链(三次握手)和断链(四次挥手)中涉及到几个关键概念字段:
- 标志位:共有 6 个,分别是:
ACK
:确认序号有效。FIN
:释放一个连接。PSH
:接收方应该尽快将这个报文交给应用层。RST
:重置连接。SYN
:发起一个新连接。URG
:紧急指针(urgent pointer)有效。
seq
:Seq 序号,占32
位,用来标识从 TCP 源端向目的端发送的字节流,发起方发送数据时对此进行标记。ack
:Ack 序号,占32
位,只有ACK
标志位等于1
时此序号字段才有效,确认方ack
等于发起方seq + 1
。注意:ACK
和ack
是两个不同的概念,不要混淆了。
延伸问题
为什么建立连接需要握手三次,两次行不行?
- 原因一:TCP连接建立前需要确认客户端和服务器双方的收发包能力。
- 第一次握手可以让服务器知道客户端的发送能力是正常的。
- 第二次握手可以让客户端知道服务器的接收和发送能力都是正常的。
- 第三次握手可以让服务器指导客户端的接收能力是正常的。
- 原因二:确保序列号可靠同步。
第二次握手服务器向客户端发送了自己的初始序列号,如果第二次握手报文丢失则客户端就无法知道服务器的初始序列号,所以需要第三次握手让服务器知道客户端已确认服务器的初始序列号。 - 原因三:阻止重复历史连接的初始化。
客户端由于某种原因发送了两个不同序号的SYN
包,因为复杂的网络环境中旧的数据包有可能先到达服务器,如果是两次握手则服务器收到旧的SYN
包就会立刻建立连接,从而造成网络异常。如果是三次握手,服务器需要回复SYN+ACK
包,客户端会对比应答的序号,如果发现是旧的报文就会给服务器发RST
包,直至正确的SYN
包到达服务器后才正常建立连接。 - 原因四:安全问题。
TCP 新建连接时内核会为连接分配一系列内存资源,如果采用两次握手可能会放大DDOS 攻击。
三次握手可以携带数据吗?
第一次握手和第二次握手不可以携带数据,第三次握手可以携带数据。假如第一次握手携带数据,如果碰到恶意攻击,那么每次在第一次握手的 SYN
报文中都会加入大量数据,会造成服务器花费大量存储空间来缓存这些数据。
为什么释放连接是四次,比建立连接多一次?
建立连接时服务器的 SYN
和 ACK
是合并发送的,而因 TCP 是全双工通信,释放连接过程中在客户端发送 FIN
包后,服务器可能还有数据需要发送,不能立即关闭连接,所以不能同时发送 FIN
包和 ACK
包,只能先确认 ACK
,然后等服务器无数据发送时再发送 FIN
包。
为什么 TIME_WAIT
状态需要经过 2MSL
才能返回到 CLOSED
状态?
MSL
是指报文在网络中的最大生存时间。
- 原因一:在客户端回复服务器
FIN
包的确认包ACK
后,这个ACK
包可能是不可达的,如果服务器收不到ACK
的话需要重新发送FIN
包。所以客户端发送ACK
后需要留出2MSL
时间(ACK
到达服务器的时间 + 服务器重发FIN
包时间),如果客户端等到2MSL
后没有收到服务器重传的FIN
包,说明可以确认服务器已经收到了客户端发送的ACK
包。 - 原因二:客户端发送完最后一个
ACK
包后,再经过2MSL
时间就可以使当前连接持续的时间内所产生的所有报文都从网络中小时,使下一个新的连接中不会出现这种旧的连接请求报文。
相关文章:

TCP 建链(三次握手)和断链(四次握手)
TCP 建链(三次握手)和断链(四次挥手) 背景简介建链(三次握手)断链(四次挥手)序号及标志位延伸问题为什么建立连接需要握手三次,两次行不行?三次握手可以携带数…...

SpringBoot集成JOOQ加Mybatis-plus使用@Slf4j日志
遇到个问题记录下,就是SpringBoot使用Mybatis和Mybatis-plus时可以正常打印日志,但是JOOQ的操作日志确打印不出来? 下面的解决方法就是将JOOQ的日志单独配置出来,直接给你们配置吧! 在项目的resources目录下创建日志…...
浅谈JavaScript中的对象赋值
目录 常见的对象赋值方式 直接赋值和对象扩展(浅拷贝)两种赋值方式区别 区别 联系 常见的对象赋值方式 1. 直接赋值:this.info this.deviceInfo,将一个对象的引用赋给另一个变量,它们引用同一个对象。 2. 对象扩…...
Java面试题-集合
Java面试题-集合 1、什么是集合?2、集合和数组的区别是什么?3、集合有哪些特点?4、常用的集合类有哪些?5、List, Set, Map三者的区别?6、说说集合框架底层数据结构?7、线程安全的集合…...

从当当网批量获取图书信息
爬取当当网图书数据并保存到本地,使用request、lxml的etree模块、pandas保存数据为excel到本地。 爬取网页的url为: http://search.dangdang.com/?key{}&actinput&page_index{} 其中key为搜索关键字,page_index为页码。 爬取的数据…...
python爬虫之JS逆向——网页数据解析
目录 一、正则 1 正则基础 元字符 基本使用 通配符: . 字符集: [] 重复 位置 管道符和括号 转义符 转义功能 转义元字符 2 正则进阶 元字符组合(常用) 模式修正符 re模块的方法 有名分组 compile编译 二、bs4 1 四种对象 2 导航文档树 嵌套选择 子节点、…...

VL53L4CX TOF开发(2)----修改测距范围及测量频率
VL53L4CX TOF开发.2--修改测距范围及测量频率 概述视频教学样品申请完整代码下载测距范围测量频率硬件准备技术规格系统框图应用示意图生成STM32CUBEMX选择MCU串口配置IIC配置 XSHUTGPIO1X-CUBE-TOF1app_tof.c详细解释测量频率修改修改测距范围 概述 最近在弄ST和瑞萨RA的课程…...

C++之noexcept
目录 1.概述 2.noexcept作为说明符 3.noexcept作为运算符 4.传统throw与noexcept比较 5.原理剖析 6.总结 1.概述 在C中,noexcept是一个关键字,用于指定函数不会抛出异常。如果函数保证不会抛出异常,编译器可以进行更多优化,…...

Kafka之Broker原理
1. 日志数据的存储 1.1 Partition 1. 为了实现横向扩展,把不同的数据存放在不同的 Broker 上,同时降低单台服务器的访问压力,我们把一个Topic 中的数据分隔成多个 Partition 2. 每个 Partition 中的消息是有序的,顺序写入&#x…...

RabbitMQ docker安装及使用
1. docker安装RabbitMQ docker下载及配置环境 docker pull rabbitmq:management # 创建用于挂载的目录 mkdir -p /home/docker/rabbitmq/{data,conf,log} # 创建完成之后要对所创建文件授权权限,都设置成777 否则在启动容器的时候容易失败 chmod -R 777 /home/doc…...
篇3:Mapbox Style Specification
接《篇2:Mapbox Style Specification》,继续解读Mapbox Style Specification。 目录 Spec Reference Root 附录: MapBox Terrain-RGB...

C#WPF数字大屏项目实战11--质量控制
1、区域划分 2、区域布局 3、视图模型 4、控件绑定 5、运行效果 走过路过,不要错过,欢迎点赞,收藏,转载,复制,抄袭,留言,动动你的金手指,财务自由...

第九十七节 Java面向对象设计 - Java Object.Finalize方法
Java面向对象设计 - Java Object.Finalize方法 Java提供了一种在对象即将被销毁时执行资源释放的方法。 在Java中,我们创建对象,但是我们不能销毁对象。 JVM运行一个称为垃圾收集器的低优先级特殊任务来销毁不再引用的所有对象。 垃圾回收器给我们一个…...

【scikit-learn009】异常检测系列:单类支持向量机(OC-SVM)实战总结(看这篇就够了,已更新)
1.一直以来想写下机器学习训练AI算法的系列文章,作为较火的机器学习框架,也是日常项目开发中常用的一款工具,最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下scikit-learn框架OCSVM模型相关知识体系。 3.欢迎批评指正,欢迎互三,跪谢一键三连! 4.欢迎…...
网络管理与运维
文章目录 网络管理与运维概念:传统网络管理:基于SNMP集中管理:基于iMaster NCE的网络管理:传统网络管理方式: 基于SNMP集中管理:交互方式:MIB:版本:SNMPv3配置网管平台&a…...
数据库查询字段在哪个数据表中
问题的提出 当DBA运维多个数据库以及多个数据表的时候,联合查询是必不可少的。则数据表的字段名称是需要知道在哪些数据表中存在的。故如下指令,可能会帮助到你: 问题的处理 查找sysinfo这个字段名称都存在哪个数据库中的哪个数据表 SELEC…...

第 400 场 LeetCode 周赛题解
A 候诊室中的最少椅子数 计数:记录室内顾客数,每次顾客进入时,计数器1,顾客离开时,计数器-1 class Solution {public:int minimumChairs(string s) {int res 0;int cnt 0;for (auto c : s) {if (c E)res max(res, …...

数据结构与算法之Floyd弗洛伊德算法求最短路径
目录 前言 Floyd弗洛伊德算法 定义 步骤 一、初始化 二、添加中间点 三、迭代 四、得出结果 时间复杂度 代码实现 结束语 前言 今天是坚持写博客的第18天,希望可以继续坚持在写博客的路上走下去。我们今天来看看数据结构与算法当中的弗洛伊德算法。 Flo…...
Ubuntu系统设置Redis与MySQL登录密码
Ubuntu系统设置Redis与MySQL登录密码 在Ubuntu 20.04系统中配置Redis和MySQL的密码,您需要分别对两个服务进行配置。以下是详细步骤: 配置Redis密码 打开Redis配置文件: Redis的配置文件通常位于/etc/redis/redis.conf。 sudo nano /etc/redis/redis.c…...
数据库连接池的概念和原理
目录 一、什么是数据库连接池 二、数据库连接池的工作原理 1.初始化阶段: 2.获取连接: 3.使用连接: 4.管理和优化: 三、数据库连接池的好处 一、什么是数据库连接池 数据库连接池(Database Connection Pooling&…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...