【网络原理】面试高频考点!!TCP协议“三次握手,四次挥手”,保姆级详解,建议收藏!

  💐个人主页:初晴~

📚相关专栏:计算机网络那些事


通过上篇文章,我们可以得知TCP通过 “确认应答” “超时重传”机制相辅相成,共同构建了 TCP的“可靠传输机制”。而为了保障建立通信和断开通信的可靠性,TCP还提供了“三次握手,四次挥手”的机制,来作为连接管理。

一、什么是“三次握手,四次挥手”

这里的“握手”与“挥手”(handshake),是一种形象的比喻。生活中握手就是一种打招呼的方式,挥手则是象征着“告别”,并没有什么实际的含义。网络中的握手与挥手,指发送不携带业务数据(没有载荷,只有报头)的数据包,起到类似打招呼或告别的效果。

事实上,握手指的就是建立连接的过程,挥手指的是断开连接的过程。

这里的连接并不是指拿个电线拴起来

  • 通信双方保存好对方的信息,就是建立连接的过程
  • 通信双方删除掉对方的信息,就是断开连接的过程

需要注意的是,在连接建立过程中,客户端主动发起连接请求;而在连接终止过程中,任何一方都可以首先提出关闭请求。此外,TCP连接的建立和终止都需要经过双方的确认,这也是“三次握手,四次挥手”的核心机制,让我们接着往下看

二、三次握手

1、三次握手的流程

  1. 第一次握手客户端向服务器发送一个SYN(同步序列号)段(即报头中的标志位“syn”值为1),表示客户端请求建立连接。这个段落包含一个初始序列号x,用于后续的数据确认。

  2. 第二次握手服务器接收到SYN段后,向客户端发送一个SYN+ACK(确认)段作为响应。这表示服务器同意建立连接,并且告知客户端它的序列号y,同时也确认了客户端的序列号。

  3. 第三次握手客户端接收到SYN+ACK后,向服务器发送一个ACK段确认服务器的序列号。至此,TCP连接建立完成,客户端和服务器可以开始数据交换。

完成以上步骤后,连接就建立完毕了。原本应该是四次交互,但是中间两次的执行时机差不多,于是系统内核就将这两次发送合并成了一次,目的是减少通信次数,提高效率。

这里的syn全称为synchronized,意为“同步的,锁”。在之前多线程的学习中是与加锁操作有关的关键字。而在此处,应该更偏向同步的意思,可以理解为客户端希望服务器与其统一步调,来完成后续的通信传输。

2、为什么是三次?

建立连接是一个“双向的操作”

  • A需要给B说,我想和你建立连接(A想保存B的信息)
  • B也需要给A说,我也想和你建立连接(B想保存A的信息)

每次请求,对方都需要做一条反馈,告诉发送方是否可以连接。因此,请求加上反馈至少就需要四次通信,而TCP将第2、3次合并到了一起,使得总共就变成了“三次握手”

举个例子:

现在有两名玩家 A 和 B 要互相连麦:

(1)玩家 A :“听得见吗?”

如果玩家 B能听到这句话,说明 A 的麦克风与 B 的耳机都能够正常使用,即 A 到 B 的通信正常。但 B 还不能确定 B 到A的通信是否正常,此时需要向 A 做出反馈

(2)玩家 B:“听得见,你能听见吗?”

如果 A 玩家能成功听见这句话,前半句“听得见”,回答了我之前的信息,A 就能知道 A 到 B 的通信正常;同时自己能听见这句话,也说明 B 的麦克风与 A 的耳机能够正常使用,即 B 到 A 的通信正常。此时 A 就能知道双方的麦克风与耳机都是正常的,但 B 还不知道,于是就需要再回答后半句 B 的问题,做出反馈:

(3)玩家 A:“听得见,我们可以开始聊天了”

当 B 听到这句话时,也就能确定双方的通信没有问题,接着就可以正常进行聊天了。

这里的麦克风就代表着发送能力耳机代表接收能力。因此“三次握手”的目的可以看做是确认通信双方各自的发送能力接收能力是否正常。 

  • 两次握手是不可行的,因为只有两次是无法完成通信双方各自的发送能力接收能力的验证的
  • 四次握手是可行的。理论上也至少要进行四次通信,只不过TCP将其优化成了三次。不过针对其它协议,握手过程就不一定是三次。

3、三次握手的意义

(1)如上文所述,验证双方的发送能力接收能力

(2)投石问路,初步验证通信链路是否通畅

比如我们日常乘坐的地铁,其实在第一班车发车之前,会先空跑一趟

目的是为了验证线路是否通畅,可以提前排查一些潜在的故障。如果在载客的情况下才发现线路故障的话,处理起来就会比较麻烦了,而相比之下空车做调整可就灵活多了。这里的空车就起到了“投石问路”的作用。

三次握手也是如此。相当于在正式通信前,先发了几个空载的报文“探路”,来“验证链路是否通畅”,相比于直接发送携带数据的报文来说,这种方式的代价就会比较小了。

(3)让通信双方在通信前,协商一些关键的参数

TCP通信时,起始数据的序号,就是通过三次握手来协商确定的。使得每次建立连接,TCP的起始序号都是不同的。其主要目的是避免“前朝的剑,斩本朝的官”

 该过程就是,A 和 B 正常连接的时候A发送了一个数据包,不过这个数据包传输的速度有些慢,在它传输的过程中,A 和 B 断开了连接,又重新建立起了连接。但此时虽然连接的还是 A 和 B 两个主机,但是可能已经是不同的应用程序了,相当于是“改朝换代”

而这个数据包就像是“旧朝遗老”,等它终于传输成功时,俨然已不是当年摸样。如果还去正常读取这个数据包,就会引起一系列问题。此时就需斩钉截铁,直接丢弃这个数据包。

为了达到这点,对于 B 来说,就需要区分,当前收到的数据时“本朝”还是“前朝”的。

于是,在每次连接时,都会尽量协商不同的起始序号,如果发现收到的数据,与起始序号差距非常大的话,就认为该数据是“前朝”的,会直接将其丢弃

三、四次挥手

1、四次挥手的流程

  1. 第一次挥手某一端(通常是从没有数据要发送的一端开始)决定关闭连接,并向另一端发送一个FIN(终止)段(标志位FIN值为1),表示它已经完成了数据发送任务。

  2. 第二次挥手接收FIN段的一端(服务器)会发送一个ACK确认段,确认接收到FIN段。此时,连接还没有完全关闭,因为这一端可能还有数据需要发送。

  3. 第三次挥手:当接收FIN段的一端完成数据发送后,它会发送自己的FIN段给最初发送FIN的一端。

  4. 第四次挥手最初发送FIN段的一端接收到对方的FIN段后,会发送ACK确认段,表明所有数据已接收完毕,连接可以关闭。此时,TCP连接正式关闭

这里的标志位“FIN”意为“Finnish”,可以理解为通信连接的终止。即双方各自把对端的信息删掉

  • 为什么流程看起来差不多,握手能优化成三次,而挥手则必须要四次?
  • 对于三次握手来说,中间的两次,ACK+SYN都是在内核中,由操作系统负责进行的。并且执行时机都是在收到发送方的 SYN 之后,同一时机,于是就直接将它们合并了
  • 对于四次挥手来说,ACK内核控制的,但是 FIN 则是通过应用程序调用 close/进程退出,来触发的,在实际执行中,这两个操作的执行时机大概率是不同的,由于执行到close前可能还要完成一系列操作,所以一般 FIN 执行都会晚于 ACK,而且很可能相差会很大。因此大部分情况下,都不会把这两个操作合并

比如在代码中调用socket.close() 时,系统内部就会发送 FIN


四、TCP的状态转换

TCP连接状态反映了TCP连接的不同阶段。这些状态可以帮助理解连接的生命周期,让我们更好地理解“三次握手,四次挥手”的流程:

 大多数状态上图中都有体现,博主接下来就主要介绍几个比较特殊的状态吧

LISTEN

  • 服务器监听客户端的连接请求。服务器把端口绑定号,就相当于进入 LISTEN 状态了。此时服务器已经初始化完毕,准备好随时迎接客户端

ESTABLISHED

  • TCP连接建立完成,可以进行业务数据的通信了。客户端和服务端都会进入的状态

 CLOSE_WAIT

  • 被动断开连接的一方,会进入这个状态。先接收到“FIN”的一方,会等待代码执行“close()”方法

如果发现,服务器端存在大量的 CLOSE_WAIT 状态的TCP连接,就说明服务器代码可能出现bug了。这时需要排查服务端代码,看看是否写了 close() ,以及是否能够及时执行。

TIME_WAIT

  • 主动断开连接的一方,会进入这个状态。一旦接收到对端的FIN段并回复了ACK,它就会进入TIME_WAIT状态。在此状态下,TCP连接保持打开一段时间。(通常是2MSL,即两倍的最大段生存时间),以确保对方的ACK段能够到达,从而确保连接正确关闭。

这时有人可能会问了,为啥不直接释放,还有等一段时间呢?

主要是为了防止最后的ACK丢包。如果最后一个ACK丢包了,此时 B 就会重传一次FIN。如果A立刻断开了连接,也就无法收到重传的FIN,更无法重新发送一次 ACK。这样 B 端就会进入死循环,迟迟无法真正断开连接

于是就让 A 先等待一段时间,如果这段时间内都没有收到 B 重发的 FIN,就可以认为之前发的 ACK成功送达了,这时才真正释放掉连接

注意:

这里的等待时间一般设置为 2MSL,其中MSL为数据报在网络传输中消耗的最大时间,不同的系统会有所差别,比如 Linux 默认为60s。这样就能确保ACK一定能够送达了


那么本篇文章就到此为止了,如果觉得这篇文章对你有帮助的话,可以点一下关注和点赞来支持作者哦。如果有什么讲的不对的地方欢迎在评论区指出,希望能够和你们一起进步✊

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/54589.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP中的PEAR是什么

PHP中的PEAR是PHP Extension and Application Repository的缩写,即PHP扩展与应用库。它是一个PHP扩展及应用的代码仓库,提供了许多常用的PHP库和工具,涵盖了页面呈现、数据库访问、文件操作、数据结构、缓存操作、网络协议、WebService等许多…

忘记 MySQL 密码怎么办:破解 root 账户密码

忘记 MySQL 密码怎么办:破解 root 账户密码 目录 忘记 MySQL 密码怎么办:破解 root 账户密码1、修改 MySQL 配置文件2、不使用密码登录 MySQL3、重置 root 用户密码4、修改 MySQL 配置文件并重启 MySQL 服务5、使用新密码登录 MySQL 如果忘记密码导致无法…

解决磁盘负载不均——ElasticSearch 分片分配和路由设置

ES 分片分配(Shard Allocation)时间点: 初始恢复(Initial Recovery)副本分配(Replica Allocation)重平衡(Rebalance)节点添加或移除 小结: 准备移除节点时&a…

使用 Vue3 和 Axios 实现 CRUD 操作

文章目录 1、准备工作2、创建 Vue 3 项目3、项目结构4、实现 CRUD 操作5、运行项目6、小结在当今的前端开发中,Vue.js 作为一款流行的 JavaScript 框架,正在被越来越多的开发者所青睐。尤其是 Vue 3 引入了 Composition API 和更优雅的响应式处理,使得模板编写和状态管理变得…

CAN转WiFi模块在仓库系统中应用

CAN转WiFi模块在仓库系统中应用 我们的LCWLAN设备在实际使用中以裸板的形式放在客户的智能总线控制器中,客户的智能总线刀片灯,柔性灯货架,柔性感应钢网柜以及智能电子料架等设备都是接到总线控制器中,然后总控制器通过CAN总线和…

Qt-QSpacerItem布局相关控件(45)

目录 描述 属性 使用 控件小结 描述 使⽤布局管理器的时候,可能需要在控件之间,添加⼀段空⽩.就可以使⽤ QSpacerItem 来表⽰ 属性 width宽度height⾼度hData⽔平⽅向的 sizePolicy • QSizePolicy::Ignored : 忽略控件的尺⼨,不对布局产⽣影响。 • QSizePol…

免费高可用软件

高可用软件是指那些能够提供高可用性、高可靠性的软件,它们在各种应用场景下都能确保系统的稳定运行。以下是四款免费的高可用软件,它们在不同领域都表现出色,能够满足各种高可用性需求。 一、PanguHA PanguHA是一款专为Windows平台设计的双…

贪心算法c++

贪心算法C概述 一、贪心算法的基本概念 贪心算法(Greedy Algorithm),又名贪婪法,是一种解决优化问题的常用算法。其基本思想是在问题的每个决策阶段,都选择当前看起来最优的选择,即贪心地做出局部最优的决…

网络通信——OSPF协议(基础篇)

这里基础是因为没有讲解OSPF中的具体算法过程,以及其中很多小细节。后续会更新。 目录 一.OSPF的基础信息 二.认识OSPF中的Router ID 三.OSPF中的三张表 四.OSPF中的度量方法(计算开销值) 五. OSPF选举DR和BDR(就是这个区域…

音视频入门基础:FLV专题(9)——Script Tag简介

一、SCRIPTDATA 根据《video_file_format_spec_v10_1.pdf》第75页到76页,如果某个Tag的Tag header中的TagType值为18,表示该Tag为Script Tag(脚本Tag,又称Data Tag、SCRIPTDATA tag)。这时如果Filter的值不为1表示未加…

【Android】Jetpack组件之LifeCycle

引言 Lifecycle组件是Android Jetpack架构组件之一,它提供了一种方法来管理Android组件(如Activity、Fragment和服务)的生命周期。Lifecycle组件帮助你执行与生命周期相关联的操作,确保在适当的时间发生适当的事情,例…

深度学习项目----用LSTM模型预测股价(包含LSTM网络简介,代码数据均可下载)

前言 前几天在看论文,打算复现,论文用到了LSTM,故这一篇文章是小编学LSTM模型的学习笔记;LSTM感觉很复杂,但是结合代码构建神经网络,又感觉还行;本次学习的案例数据来源于GitHub,在…

越差越好?为什么简单反而赢了,这背后究竟有什么秘诀?

你有没有发现,软件界里那些最成功的产品,往往并不是最复杂、最强大的?我们用的很多东西,看起来功能普通,甚至有些粗糙,但就是这样简陋的设计,反而成了市场上的赢家。 也许你玩过Flappy Bird这个游戏:它的设计非常简单,玩家只需要点击屏幕让小鸟飞行,避开管道障碍。游…

【微服务】springboot 实现动态修改接口返回值

目录 一、前言 二、动态修改接口返回结果实现方案总结 2.1 使用反射动态修改返回结果参数 2.1.1 认识反射 2.1.2 反射的作用 2.1.3 反射相关的类 2.1.4 反射实现接口参数动态修改实现思路 2.2 使用@ControllerAdvice 注解动态修改返回结果参数 2.2.1 注解作用 2.2.2 实…

Llama 3.2 智能代理开发教程

构建研究代理可能很复杂,但使用 LangChain 和 Ollama,它会变得更加简单和模块化。 在本教程中,我们将向你展示如何基于Llama 3.2创建一个研究代理,该代理可以路由查询、执行网络搜索并使用工作流和 LLM 的组合生成详细响应。最后…

使用 Python 实现遗传算法进行无人机路径规划

目录 使用 Python 实现遗传算法进行无人机路径规划引言1. 遗传算法概述1.1 定义1.2 基本步骤1.3 遗传算法的特点 2. 使用 Python 实现遗传算法2.1 安装必要的库2.2 定义类2.2.1 无人机模型类2.2.2 遗传算法类 2.3 示例程序 3. 遗传算法的优缺点3.1 优点3.2 缺点 4. 改进方向5. …

出栈入栈次序匹配

学习栈的过程中,我们一定见过下面两题,在当时我们可能费尽心思才找出不可能的一个出栈序列,但是如果进栈元素很多,那么找出出栈序列时4,头发就要掉光了!那么我们是否可以实现一串代码,来帮助我们…

MySQL 篇-深入了解视图、SQL 优化(主键优化、order by 优化、group by 优化、update 优化等)

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 SQL 优化 1.1 SQL 优化 - 插入数据 1.2 SQL 优化 - 主键优化 1.2.1 页分裂 1.2.2 页合并 1.2.3 主键设计原则 1.3 SQL 优化 - order by 优化 1.3.1 单字段排序 1.…

重学SpringBoot3-集成Redis(五)之布隆过滤器

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞👍收藏⭐评论✍ 重学SpringBoot3-集成Redis(五)之布隆过滤器 1. 什么是布隆过滤器?基本概念适用场景 2. 使用 Redis 实现布隆过滤器项目依赖Redis 配置…

【python实操】python小程序之对象的属性操作

引言 python小程序之对象的属性操作 文章目录 引言一、对象的属性操作1.1 题目1.2 代码1.3 代码解释 二、思考2.1 添加属性2.2 获取属性 一、对象的属性操作 1.1 题目 给对象添加属性 1.2 代码 class Cat:# 在缩进中书写⽅法def eat(self):# self 会⾃动出现,暂不管print(f…