深入理解 TCP 的握手与挥手机制:为何握手 3 次,挥手 4 次?

在网络通信的世界里,TCP(Transmission Control Protocol,传输控制协议)是一种非常重要的协议,它确保了数据在网络中的可靠传输。而 TCP 的连接建立(握手)和连接断开(挥手)过程有着特定的步骤和逻辑,其中握手需要 3 次,挥手需要 4 次,这背后蕴含着深刻的原理。

一、TCP 握手的 3 次过程及原理

  1. 第一次握手

    • 客户端向服务器发送一个带有 SYN(Synchronize Sequence Numbers,同步序列号)标志的数据包,这个数据包中还包含一个随机生成的初始序列号(Sequence Number),记为 seq = x。此时客户端进入 SYN_SENT(同步已发送)状态。
    • 这一步的作用是客户端告诉服务器,“我想要建立连接”,并且通过发送初始序列号,为后续的数据传输做准备。这个序列号在后续的数据包确认和排序中起着关键作用。
  2. 第二次握手

    • 服务器收到客户端的 SYN 数据包后,需要向客户端回应一个数据包。这个数据包包含两个关键信息:一是 SYN 和 ACK(Acknowledgment,确认)标志都被置位,二是服务器自己的初始序列号,记为 seq = y,同时确认号(Acknowledgment Number)设置为客户端的序列号加一,即 ack = x + 1。此时服务器进入 SYN_RCVD(同步收到)状态。
    • 这一步的意义在于服务器告诉客户端,“我收到了你的连接请求,并且我也同意建立连接”。服务器发送自己的初始序列号是为了在后续的通信中标识自己发送的数据,而确认号的设置是对客户端发送的序列号的确认,表示服务器已经成功接收到了客户端的数据包,期待下一个序列号为 x + 1 的数据包。
  3. 第三次握手

    • 客户端收到服务器的回应数据包后,再向服务器发送一个 ACK 数据包,这个数据包的确认号为服务器的序列号加一,即 ack = y + 1,此时客户端进入 ESTABLISHED(已建立连接)状态。服务器收到这个 ACK 数据包后,也进入 ESTABLISHED 状态,至此,TCP 连接建立成功。
    • 这一步是客户端对服务器回应的确认,告诉服务器,“我已经收到了你的同意建立连接的数据包,我们可以开始数据传输了”。通过三次握手,客户端和服务器之间就建立了一个可靠的双向连接,双方都知道了对方的初始序列号,并且可以根据序列号对数据包进行排序和确认,确保数据的正确传输。

二、为什么 TCP 握手需要 3 次而不是 2 次或 4 次?

  1. 不是 2 次的原因

    • 如果只进行 2 次握手,当客户端发送的第一个连接请求数据包在网络中延迟了一段时间后才到达服务器,而此时客户端可能因为长时间没有收到服务器的回应已经重新发送了一个新的连接请求并成功建立了连接,完成了数据传输后关闭了连接。但是,那个延迟的连接请求数据包此时到达了服务器,服务器会误以为这是一个新的连接请求,并向客户端发送回应数据包,建立连接。而客户端此时并不会理会这个连接,因为它已经完成了任务并关闭了相关资源,这样就会导致服务器浪费资源等待一个不存在的连接。
    • 3 次握手可以很好地避免这种情况,因为第三次握手是客户端对服务器回应的确认,如果客户端没有发送第三次握手的数据包,服务器就会知道这个连接请求可能是无效的或者已经超时,从而不会建立连接,避免了资源的浪费。
  2. 不是 4 次的原因

    • 3 次握手已经能够满足可靠建立连接的需求。在第三次握手时,客户端已经向服务器确认了连接请求,并且双方都知道了对方的初始序列号,具备了开始数据传输的条件。如果再增加一次握手,会增加通信的开销和延迟,而没有实际的必要。经过多年的实践和研究证明,3 次握手是在保证连接可靠性的前提下最有效的方式。

三、TCP 挥手的 4 次过程及原理

  1. 第一次挥手

    • 当客户端想要关闭连接时,它会向服务器发送一个带有 FIN(Finish,结束)标志的数据包,表示客户端不再发送数据,但仍然可以接收数据。此时客户端进入 FIN_WAIT_1(终止等待 1)状态。
    • 这一步是客户端主动发起的关闭连接请求,告诉服务器它已经完成了数据的发送,希望结束数据传输的阶段。
  2. 第二次挥手

    • 服务器收到客户端的 FIN 数据包后,会向客户端发送一个 ACK 数据包,表示服务器已经收到了客户端的关闭请求,并且确认客户端之前发送的数据都已经成功接收。此时服务器进入 CLOSE_WAIT(关闭等待)状态,客户端收到这个 ACK 数据包后进入 FIN_WAIT_2(终止等待 2)状态。
    • 这一步是服务器对客户端关闭请求的确认,让客户端知道它的请求已经被服务器接收,并且服务器正在处理剩余的数据。
  3. 第三次挥手

    • 服务器处理完剩余的数据后,也会向客户端发送一个带有 FIN 标志的数据包,表示服务器也完成了数据的发送,希望关闭连接。此时服务器进入 LAST_ACK(最后确认)状态。
    • 这一步是服务器主动发起的关闭连接请求,告诉客户端它也已经完成了所有的数据处理工作,准备结束连接。
  4. 第四次挥手

    • 客户端收到服务器的 FIN 数据包后,会向服务器发送一个 ACK 数据包,确认服务器的关闭请求。此时客户端进入 TIME_WAIT(时间等待)状态,经过一段时间后(这个时间通常是 2 倍的最大段生存期,即 2MSL),客户端才会进入 CLOSED(关闭)状态。服务器收到这个 ACK 数据包后,直接进入 CLOSED 状态,至此,TCP 连接完全关闭。
    • 这一步是客户端对服务器关闭请求的最终确认,确保双方都能够正常关闭连接。而客户端进入 TIME_WAIT 状态的目的是为了防止最后一个 ACK 数据包丢失,如果丢失,服务器会重新发送 FIN 数据包,客户端在 TIME_WAIT 状态下可以重新发送 ACK 数据包进行确认。

四、为什么 TCP 挥手需要 4 次而不是 3 次?

  1. 数据传输的双向性

    • TCP 连接是全双工的,即数据可以在两个方向上同时传输。在关闭连接时,客户端和服务器都可能还有未发送完的数据需要继续发送。当客户端发送 FIN 数据包表示它不再发送数据时,服务器可能还有数据要发送给客户端,所以服务器需要先发送 ACK 数据包确认客户端的关闭请求,然后再发送 FIN 数据包表示自己也准备关闭连接。
    • 这就导致了在关闭连接的过程中,需要分别处理客户端到服务器和服务器到客户端两个方向的数据传输结束的情况,所以需要 4 次挥手来确保双方都能够正确地关闭连接。
  2. 保证数据的完全传输

    • 在服务器收到客户端的 FIN 数据包后,它需要时间来处理剩余的数据,并确保这些数据都已经成功发送给客户端。因此,服务器不能立即关闭连接,而是需要先发送 ACK 数据包确认客户端的请求,然后在处理完剩余数据后再发送 FIN 数据包。这样可以保证数据的完整性和可靠性,避免数据丢失。
    • 如果采用 3 次挥手,可能会导致服务器在还有数据未发送完的情况下就被强制关闭连接,从而造成数据丢失或者传输错误。

通过以上对 TCP 握手和挥手机制的详细解析,我们可以清楚地了解到为什么握手是 3 次,挥手是 4 次。这些机制是为了确保 TCP 连接的可靠性、数据的正确传输以及资源的合理利用。理解这些原理对于网络开发人员、系统管理员以及对网络通信感兴趣的人来说都非常重要,它有助于我们更好地理解网络通信的本质,解决网络连接中的各种问题,提高网络应用的性能和稳定性。

文章(专栏)将持续更新,欢迎关注公众号:服务端技术精选。欢迎点赞、关注、转发

个人小工具程序上线啦,通过公众号(服务端技术精选)菜单【个人工具】即可体验,欢迎大家体验后提出优化意见

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Python-数据爬取(爬虫)

在数据驱动的时代,Python以其强大的数据处理能力和丰富的库资源,成为数据爬取的首选语言。通过Python,你可以轻松地从网页中抓取所需的数据,无论是价格信息、新闻内容还是用户评论,都能一一收入囊中。使用requests库发…

基于51单片机水位监测控制报警仿真设计

基于51单片机水位监测控制报警仿真设计 1. 主要功能:2. 讲解视频:3. 仿真4. 程序代码5. 设计报告6. 设计资料内容清单&&下载链接资料下载链接: 基于51单片机水位监测控制报警仿真设计( proteus仿真程序设计报告讲解视频) …

JavaFX在Linux aarch64上运行

1.适配Jdk Linux开发项目安装在麒麟系统,无法安装,经查询因cpu架构不同导致无法运行 https://www.oracle.com/sg/java/technologies/downloads/#java21 该链接可下载jdk21,Linux aarch64版本。 2.适配Javafx模块 替换jdk之后,JavaFX仍无…

3D区块多重渐变围栏

这里主要用到的就是threejs的shader,至于其他知识点,可以参考json生成3d区域 下面的主要代码: import * as THREE from three; import { OrbitControls } from three/addons/controls/OrbitControls.js import { EffectComposer } from th…

【NLP】使用 SpaCy、ollama 创建用于命名实体识别的合成数据集

命名实体识别 (NER) 是自然语言处理 (NLP) 中的一项重要任务,用于自动识别和分类文本中的实体,例如人物、位置、组织等。尽管它很重要,但手动注释大型数据集以进行 NER 既耗时又费钱。受本文 ( https://huggingface.co/blog/synthetic-data-s…

Git代码托管(三)可视化工具操作(1)

常见的可视化操作工具有 一、官方网页 如码云、gitlab,自带了常见的git操作。 以码云为例: 1、创建分支: 进入分支目录,点击 新建分支 按钮, 在弹出框中输入新分支名称,点击确定即可一键创建分支&…

STL学习-无序容器-unordered set和unorderde multiset

1.定义及初始化 #include <unordered set> #include <iostream> using namespace std; //输出s中的所有元素 template<typename T> void Show(const T& s) { for(auto&x:s) cout << x<<" ";cout << endl; } int main()…

鸿蒙(Harmony)实现滑块验证码

在Android和ios两端已经使用的滑块验证码框架还未适配鸿蒙版&#xff0c;于是需要自己去实现类似如下的滑块验证码&#xff1a; 那么实现这样的验证码主要涉及到几个内容&#xff1a; 1、自定义弹窗 2、base64图片转换 3、滑动组件与滑块的联动&#xff0c;以及横移距离转换…

《华为工作法》读书摘记

无论做什么事情&#xff0c;首先要明确的就是做事的目标。目标是引导行动的关键&#xff0c;也是证明行动所具备的价值的前提&#xff0c;所以目标管理成了企业与个人管理的重要组成部分。 很多时候&#xff0c;勤奋、努力并不意味着就一定能把工作做好&#xff0c;也并不意味…

三维测量与建模笔记 - 3.3 张正友标定法

上图中&#xff0c;提到了世界坐标系在张正友标定法中的设计&#xff0c;可以理解为将世界坐标系的原点放到了棋盘格左上角点的位置&#xff0c;并且棋盘格平面上所有点的Z为0&#xff0c;将Z规定为0的话&#xff0c;可以简化掉一个维度&#xff08;列向量r3&#xff09;。去掉…

【课程总结】day34:多模态大模型之ViT模型、CLIP模型论文阅读理解

前言 在【课程总结】day31&#xff1a;多模态大模型初步了解一文中&#xff0c;我们对多模态大模型的基本原理有了初步了解&#xff0c;本章内容将通过论文阅读理解&#xff0c;更进一步理解多模态大模型中所涉及的 Vit 架构、Transformer在视觉应用的理念以及 Clip图像与文本…

国药准字生发产品有哪些?这几款不错

头秃不知道怎么选的朋友们看这&#xff0c;基本上市面上火的育发精华我都用了个遍了&#xff0c;陆陆续续也花了有大几w了&#xff0c;都是真金白银总结出来的&#xff0c;所以必须要给掉发人分享一些真正好用的育发产品&#xff0c;大家可以根据自己实际情况来选择。 1. 露卡菲…

golang分布式缓存项目 Day 1

注&#xff1a;该项目原作者&#xff1a;https://geektutu.com/post/geecache-day1.html。本文旨在记录本人做该项目时的一些疑惑解答以及部分的测试样例以便于本人复习。 LRU缓存淘汰策略 三种缓存淘汰策略 FIFO&#xff08;First In, First Out&#xff09;先进先出 原理&…

Android View事件分发

目录 1.什么是View事件分发&#xff1f; 2.事件的类型 3.事件的发生 4.事件分发的方法 4.1 dispatchTouchEvent() 4.2 onTouchEvent() 4.3 onInterceptTouchEvent() 5.滑动冲突 5.1 外部拦截法 5.2内部拦截法 6.onTouch的执行高于onClick 7. onTouch()和onTouchEve…

Elasticsearch常用接口_添加数据

插入es数据&#xff1a;_index/_type/ POST { "tabTitle": "森图表_test", "chtTabTitle": "森图表_test", "status": 0 } 注意&#xff1a;Elasticsearch 6.0.0及更高版本中&#xff0c;索引只能包含一个映射类型

springboot养老院信息管理系统-计算机设计毕业源码30958

目 录 摘要 1绪论 1.1 研究背景 1.2 研究意义 1.3论文结构与章节安排 2 系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据新增流程 2.2.2 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章小结 3 系统总体设…

OkHttp网络请求框架

添加依赖 在 build.gradle 文件中添加 OkHttp 依赖&#xff1a; dependencies {implementation("com.squareup.okhttp3:okhttp:4.10.0") }使用OkHttp发起GET请求 同步请求 public class MainActivity extends AppCompatActivity {// Used to load the okhttptes…

基于sealos部署的集群部署dashboard

1、下载yaml文件进行部署 rootmaster-1:~# wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml2、修改service的访问模式 rootmaster-1:~# vim recommended.yaml kind: Service apiVersion: v1 metadata:labels:k8s-app: kube…

手机贴膜气泡识别组件定位图像分割系统:快速图像识别

手机贴膜气泡识别组件定位图像分割系统源码&#xff06;数据集分享 [yolov8-seg-C2f-Parc&#xff06;yolov8-seg-KernelWarehouse等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge …

C语言 | Leetcode C语言题解之第538题把二叉搜索树转换为累加树

题目&#xff1a; 题解&#xff1a; struct TreeNode* getSuccessor(struct TreeNode* node) {struct TreeNode* succ node->right;while (succ->left ! NULL && succ->left ! node) {succ succ->left;}return succ; }struct TreeNode* convertBST(stru…