[Linux] TCP协议介绍(2): TCP协议的“三次握手“过程分析、超时重传机制介绍...

上一篇文章中, 已经介绍了TCP协议的数据格式, 简单分析了其与UDP协议 关于可靠性方面的差异

本篇文章, 介绍分析一下 使用TCP协议通信, 非常重要的一个过程: 三次握手

TCP的"三次握手"

TCP协议是有连接的传输层协议, 即使用TCP协议通信, 是需要建立连接的

TCP协议建立连接的过程, 叫做"三次握手", 这个过程具体是什么? 为什么是三次? 这两个问题可以分析一下

TCP"三次握手"建立连接的过程, 用图片展示是这样的:

|huger

注意, 通信中发送的 SYN SYN+ACK ACK, 并不是发送报文中携带的数据, 而是指发送的报文报头中设置的标记位

此图中, Client代表 客户端 Server代表 服务端, 不同颜色的片段表示不同的状态

那么, 这个"三次握手"的过程就是:

  1. 客户端先发送连接请求, 即 将TCP报文中SYN标记位设置为1, 然后再将整个报文发送给服务端(一般情况下不会携带数据)

    客户端发送了此报文之后, 客户端进入SYN_SENT状态, 表示已发送了建立连接的请求

  2. 如果服务端收到了 客户端发送的连接请求, 那么服务端就会应答客户端的请求, 即 将TCP报文中SYNACK标记位都设置为1, 然后再将整个应答报文发送给客户端(同样一般不会携带数据)

    服务端发送了此 应答报文之后, 服务端进入SYN_RCVD状态, 表示已经应答了客户端的连接请求

  3. 然后客户端就应该收到 来自服务端的应答报文 之后, 客户端就需要再向服务端发送一个应答, 即 客户端将TCP报文中ACK标记位设置为1, 然后将报文发送给服务端

    客户端发送了此次应答报文之后, 客户端就会进入ESTABLISHED状态, 客户端认为连接建立成功

  4. 最后, 服务端应该收到来自客户端的应答报文, 收到之后, 服务端不会再发送应答报文, 而是进入ESTABLISHED状态, 服务端认为连接建立成功

"三次握手"的实际就是 客户端和服务端在互相发送报文, 用来确认连接的过程

如何理解简单TCP的连接

连接, 在网络中是一个比较抽象的概念

TCP协议是面向连接的, 那么 如何理解TCP连接呢?

一个主机是可以同时建立大量的连接的, 那么操作系统就需要同时维护、管理大量的连接

按照以往操作系统管理大量进程、文件等的经验, 操作系统一定会针对每个连接 均维护 包含此连接所有属性的结构体. 不过, 由于TCP连接的管理较为复杂, 所以对应需要维护的结构体不止一个

那么, 也就是说, 当客户端或服务端 为了维护TCP连接 创建了对应的结构体对象 并 已经完成了结构体内数据的填充, 就表示 客户端或服务端认为此次TCP连接已完成且成功

为什么是"三次握手"

上面 介绍了"三次握手"的过程, 但是 为什么是三次?

一次不行吗?

我们已经了解到, 当服务端针对此次TCP连接 创建并维护了对应的结构体对象 并 完成了结构体数据的填充时, 服务端就认为连接建立完成

既然是操作系统创建维护一些结构体, 那么就一定有时间和资源上的消耗

如果是"一次握手", 就表示 客户端发送SYN连接请求之后, 就直接认为自己创建好了连接, 服务端收到请求 不需要应答, 服务端就同样直接认为连接已建立

虽然, "一次握手"也同样可能成功的建立连接

但是, 如果只是"一次握手" 就会出现一些问题:

  1. 客户端和服务端无法正确协定、同步 双方的初始序号

    TCP报头存在 序号, 此字段的初始值是在建立连接时, 客户端和服务端互相协定、同步的

    如果只是"一次握手", 那么只能同步客户端的初始序号, 因为只有客户端发送了携带初始序号的报文

  2. 由于网络延迟, 客户端可能多次发送连接请求, 服务端就有可能多次建立连接

    服务端多次建立了连接, 即 多次创建了 一些维护连接所需的结构体, 但是只有一套是有效的

    这样, 会造成对服务端资源的无效占用

两次不行吗?

如果是"两次握手", 就表示 客户端先发送SYN连接请求, 服务端收到请求 需要SYN+ACK应答, 然后服务端认为连接建立完成, 客户端收到服务端的应答之后, 客户端认为连接建立完成

我们知道, 客户端和服务端认为连接建立完成的标志是 系统已经创建并填充完成了 一系列维护TCP连接所需的结构体

那么如果"两次握手", 则是 服务端系统先完成了 创建并填充 一系列维护连接所需的结构体

这就可能出现一个问题: 如果客户端不断地发送请求, 但是不接收服务端的请求, 然后导致 服务端不断地 维护TCP连接, 而客户端并不维护连接.

这就实现了对服务端主机的攻击: 服务端会不断地消耗时间和空间资源, 用于维护TCP连接, 而客户端不会

并且, 由于 服务端依旧是 仅接收一次客户端的报文 就确认连接已建立, 所以还可能会出现 仅"一次握手"出现的问题:

  1. 由于网络延迟, 客户端可能多次发送连接请求, 服务端就有可能多次建立连接

    服务端多次建立了连接, 即 多次创建了 一些维护连接所需的结构体, 但是只有一套是有效的

    这样, 会造成对服务端资源的无效占用

“两次握手”, 理论上来说 不会出现无法协定、同步通信双方初始序号的问题

因为, 客户端发送连接请求可以携带初始序号, 服务端进行应答也可以携带初始序号

即使存在网络延迟, 导致客户端发送了多个连接请求. 服务端也会针对多个连接请求一一进行应答

所有应答报文都会填充对应的确认序号和初始序号, 所以客户端只要收到了应答报文, 就可以确认服务端应答的目标 以及 服务端的初始序号. 然后, 连接建立成功

如果, 客户端没有收到应答报文, 那这就意味着连接还没有建立成功, 客户端可能会继续发送请求, 直到成功接收应答报文

如果是三次呢?

"三次握手"的过程已经简单的分析了一下

|huge

从图中可以看到, Client率先进入了ESTABLISHED状态, 也就是说 Client率先完成了维护TCP连接操作

然后, Server进入了ESTABLISHED状态, 这样 让客户端先完成维护连接的操作, 可以避免像"两次握手"那样 服务端被攻击, 至少客户端也要付出相同的代价

其次, 因为在ClientServer进入ESTABLISHED状态之前, 都经历了一收一发, 所以不会出现 无法正确协定和同步双方初始序号的情况

并且, "三次握手"通过三次报文传输, 顺便完成了 客户端的发送(SYN请求)和接收(SYN+ACK应答)能力的检测 以及 服务端的发送(SYN+ACK应答)和接收(ACK应答)能力的检测

"三次握手"是可以完成上面这些功能的最少的次数, 如果"四次握手"或更多次数的握手, 也只是徒增连接消耗罢了

协定、同步双方初始序号

上面展示"三次握手"过程的图, 没有展示出 通信双方同步初始序号的过程

"三次握手"过程可以这样展示:

|huge

SYN ACK 大写的, 表示设置的标记位

seq ack 小写的, 表示序号 和 确认序号

整个 协定、同步初始序号的过程是:

  1. 客户端发送连接请求, 携带随机初始序号的seq = x

  2. 服务端收到请求, 读取到客户端的初始序号, 应答报文 携带随机初始序号的seq = y, 且填充确认序号ack = x+1

  3. 客户端收到应答, 读取确认序号 确认服务端已同步客户端初始序号, 同时 读取到服务端的初始序号, 然后 应答报文 填充序号seq = x+1和确认序号ack = y+1

    客户端确认连接建立

  4. 服务端收到应答, 读取确认序号 确认客户端已同步服务端初始序号

    服务端确认连接建立

整个过程中, 客户端和服务端, 都是经过一发一收 读取收到确认序号之后, 才确认的初始序号已同步

"一次握手"和"两次握手"无法完善这个过程

了解了"三次握手"的过程, 回到上面提到的一个问题:

发送方如何在第一次发送数据之前, 就知晓接收方的窗口大小呢?

这个答案就是: 双方会 在"三次握手"阶段对窗口大小进行交换、同步

6. RST标记位

"三次握手"的过程中, 报文的发送是需要时间的

在客户端进行第三次握手之后, 客户端实际就已经认为本次TCP连接已经建立完成了

客户端完成连接建立之后, 会干什么? 会向服务端发送数据

但是, 有一个问题是, 如果服务端没有收到第三次握手的报文, 但是客户端已经向服务端开始发送数据了, 怎么办?

在服务端还在等待第三次握手的报文时, 服务端还没有进入ESTABLISHED状态, 客户端已经发送通信数据到服务端了, 此时 服务端就会意识到 TCP连接出了问题

然后 服务端就会向客户端发送 设置了RST标记位的报文, 让客户端重置TCP连接并重新进行"三次握手"

这就是RST标记位的作用, 让客户端重新建立TCP连接, 所以RST标记位 叫做复位标记位

除了上面出现的场景, RST还可以用于由于长时间不进行通信, 被服务器单方面断掉的TCP连接中

TCP的超时重传机制

TCP的超时重传机制表示, TCP通信中, 如果一端长时间没有收到来自对端的应答, 那么就会重新发送没有收到应答的报文

但是, 长时间没有收到对端应答有两种情况:

  1. 报文根本就没有发送到对端, 在传输过程中丢包了
  2. 对端接收到报文了, 并且也发送了应答报文, 但是对端的应答却在传输的过程中丢包了

这两种情况的区别是, 1. 对端没收到数据 2. 对端收到了数据

  1. 对端没有收到数据

    此时, 只需要在超时之后 将报文重新发送给对端 就可以了

  2. 对端收到了数据

    如果对端已经收到了数据, 但是对端的应答报文丢了

    那么, 当报文重新发送给对端之后, 对端会再次发送应答报文

    但是, 此时 对端就会接收到重复的数据. 但重复的报文、数据是没用的 需要丢弃, 所以 TCP协议需要有能力识别接收的报文是否重复

    这就要用到TCP报文的 序号字段. 只要两个报文的序号字段相同, 就说明收到了相同的报文

TCP协议的超时重传机制, 说明了 TCP报文在发送出去 或 接收到之后, 并不会立刻丢弃, 而是会存储一段时间

这也是 TCP超时重传机制的基础

那么, TCP如何界定 是否超时?

最理想的情况, 就是可以找到一个最短的时间, 保证此次发送之后"确认应答一定能在这个时间内返回".

但是, 网络环境是会变化的, 所以这个最短的时间也是不可能固定下来的

所以Linux中TCP协议就需要自行的界定、计算 超时边界

不过, 重传不会一直进行, 当重传累计到一定的重传次数, TCP认为网络或者对端主机出现异常, 强制关闭连接

关于超时的设定:

如果超时时间设的太长, 会影响整体的重传效率

如果超时时间设的太短, 有可能会频繁发送重复的包


至此, 本篇文章主要内容结束

感谢阅读~

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

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

相关文章

JVM-基础知识

JVM-基础知识 什么是JVM JVM是一种跨语言的平台,任何语言只要能编译成.class文件都可以被JVM运行。JVM只和.class文件有关系,和Java语言没关系。JVM是一种虚拟机规范。 java文件是如何交给JVM执行的 JVM的常见实现 HostStop:Oracle官方另外还有IBM的J9、…

Java--Arrays类

1.数组的工具java.util.Arrays 2.由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。 3.查看JDK帮助文档 4.Arrays类中的方法都是static修饰静态的静态方法&…

MyBatis操作数据库(一)

什么是MyBatis? MyBatis是一个优秀的持久层框架,⽤于简化JDBC的开发。 MyBatis本是Apache的⼀个开源项⽬iBatis,2010年这个项目由apache迁移到了googlecode,并且改名为MyBatis。 简单来说MyBatis是更加简单完成数据和数据库交互的框架 什么…

2-6 基于matlab2018B的语音信号降噪和盲源分离GUI界面

基于matlab2018B的语音信号降噪和盲源分离GUI界面,包括维纳滤波,小波降噪、高通、低通、带通滤波,及提出的滤波方法。每个功能均展示降噪前后声音效果并外放出来。程序已调通,可直接运行。 2-6 语音信号降噪 盲源分离 GUI界面 - 小…

canvas学习

Canvas API 提供了一个通过 JavaScript 和 HTML 的 元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。 Canvas 的基本用法 <canvas> 元素 <canvas id"tutorial" width"150" height"150&quo…

[Python]Anaconda相关命令

环境操作相关命令 查看所有环境 conda env list创建环境 conda create --name cahttts python3.10激活环境 conda activate cahttts安装依赖文件 pip install -r requirements.txt查看GPU型号 nvidia-smi -LGPU 0: NVIDIA A10 (UUID: GPU-9f1fc9cf-582a-25ac-849c-2f77343…

ESD与EOS区别

最近小白在做项目时&#xff0c;被一个实习生问道了&#xff0c;关于EOS与ESD区别。说实话&#xff0c;以前专注于测试debug的我&#xff0c;在回答对方时&#xff0c;并没法做到太全面的解答。于是乎&#xff0c;借助周内的空闲时间&#xff0c;小白还是简单学习总结了一番。 …

Harbor镜像中心搭建

文章目录 Harbor镜像中心搭建前置条件下载Harbor创建CA证书配置Harbor开始启动地址映射访问配置本地登录配置外部虚拟机访问 Harbor镜像中心搭建 Harbor是一个镜像中心&#xff0c;我们所熟知的DockerHub就是一个镜像中心&#xff0c;我们可以把我们打包的镜像放在镜像中心中供…

关于Java

关于Java Java语言关于并发JVM调优工具写在最后 Java语言 Java语言作为当下主流开发语言&#xff0c;其面向对象的开发模式以及一次编译多次运行&#xff0c;跨平台运行以及自动的垃圾回收机制可以说是给开发者节省了很大的时间用于逻辑功能的开发&#xff0c;那么在开发过程中…

【Linux】pycharmgit相关操作

目录 1. git安装配置2. 相关内容3. pycharm连接远程仓库3.1 配置3.2 clone远程仓库3.3 本地仓库上传远程 4. 分支管理4.1 更新代码4.2 新建分支4.3 分支合并4.4 代码比对 5. 版本管理6. 命令行操作6.1 配置git6.2 基础操作6.3 分支操作 1. git安装配置 下载链接&#xff1a;官…

07--Zabbix监控告警

前言&#xff1a;和普米一样运维必会的技能&#xff0c;这里总结一下&#xff0c;适用范围非常广泛&#xff0c;有图形化界面&#xff0c;能帮助运维极快确定问题所在&#xff0c;这里记录下概念和基础操作。 1、zabbix简介 Zabbix是一个基于 Web 界面的企业级开源解决方案&a…

【C++】C++入门的杂碎知识点

思维导图大纲&#xff1a; namespac命名空间 什么是namespace命名空间namespace命名空间有什么用 什么是命名空间 namespace命名空间是一种域&#xff0c;它可以将内部的成员隔绝起来。举个例子&#xff0c;我们都知道有全局变量和局部变量&#xff0c;全局变量存在于全局域…

SQLAlchemy:filter()和filter_by()的微妙差异

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 在Python编程中&#xff0c;SQLAlchemy是一个强大的ORM&#xff08;对象关系映射&#xff09;工具&#xff0c;它允许使用Python代码来操作数据库。然而&#xff0c;对于新手来说&#xff0c;SQLAlchemy中的一些函数…

mybatis-plus使用拦截器实现sql完整打印

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen 在使用mybatis-plus&#xff08;mybatis&#xff09;的时候&#xff0c;往往需要…

英伟达开源最强通用模型Nemotron-4 340B:开启AI合成数据新纪元

【震撼发布】 英伟达最新力作——Nemotron-4 340B,一个拥有3400亿参数的超级通用模型,震撼登场!这不仅是技术的一大飞跃,更是AI领域的一次革命性突破! 【性能卓越】 Nemotron-4 340B以其卓越的性能超越了Llama-3,专为合成数据而生。它将为医疗健康、金融、制造、零售等行…

Studio One 6.6.2 for Mac怎么激活,有Studio One 6激活码吗?

如果您是一名音乐制作人&#xff0c;您是否曾经为了寻找一个合适的音频工作站而苦恼过&#xff1f;Studio One 6 for Mac是一款非常适合您的MacBook的音频工作站。它可以帮助您轻松地录制、编辑、混音和发布您的音乐作品。 Studio One 6.6.2 for Mac具有直观的界面和强大的功能…

C++初学者指南第一步---1. C++开发环境设置

C初学者指南第一步—1. C开发环境设置 目录 C初学者指南第一步---1. C开发环境设置1.1 工具1.1.1 代码编辑器和IDE1.1.2 Windows1.1.3 命令行界面 1.2 编译器1.2.1 gcc/g (支持Linux/Windows/MacOSX)1.2.2 clang/clang (支持Linux/Windows/MacOS)1.2.3 Microsoft Visual Studio…

《面向对象程序设计》第3章 类与对象(判断、选择、填空)-练习

1-1 常量对象可以使用常量成员函数。 T F | 参考答案 答案 T 2分 1-2 在定义常量成员函数和声明常量成员函数时都应该使用const关键字。 T F | 参考答案 答案 T 2分 1-3 对象间赋值将调用拷贝构造函数。 T F | 参考答案 答案 F 2分 1-4 对象数组生命期…

奇思妙想-可以通过图片闻见味道的设计

奇思妙想-可以通过图片闻见味道的设计 偷闲半日享清闲&#xff0c;炭火烧烤乐无边。肉串飘香引客至&#xff0c;笑语欢声绕云间。人生难得几回醉&#xff0c;且把烦恼抛九天。今宵共饮开怀酒&#xff0c;改日再战新篇章。周四的傍晚&#xff0c;难得的闲暇时光让我与几位挚友相…

PAT B1026. 程序运行时间

题目描述 要获得一个C语言程序的运行时间,常用的方法是调用头文件time.h,其中提供了clock(&#xff09;函数,可以捕捉从程序开始运行到clock()被调用时所耗费的时间。这个时间单位是clock tick,即“时钟打点”。同时还有一个常数CLK_TCK——给出了机器时钟每秒所走的时钟打点数…