[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,一经查实,立即删除!

相关文章

一千题,No.0070(组合数的和)

给定 N 个非 0 的个位数字,用其中任意 2 个数字都可以组合成 1 个 2 位的数字。要求所有可能组合出来的 2 位数字的和。例如给定 2、5、8,则可以组合出:25、28、52、58、82、85,它们的和为330。 输入格式: 输入在一行…

【Android面试八股文】HandlerThread是什么?有什么使用场景?

文章目录 一、HandlerThread是什么?1.1 HandlerThread 简介1.2 HandlerThread 源码分析1. 构造函数2. run 方法3. 获取 Looper4. 退出 Looper5. 总结二、HandlerThread有什么使用场景示例代码一、HandlerThread是什么? 1.1 HandlerThread 简介 HandlerThread 是 Android 提…

编程基础知识编程实例解析:深度探索与实战应用

编程基础知识编程实例解析:深度探索与实战应用 编程,作为现代信息社会的核心技能之一,对于理解和应用计算机技术具有至关重要的意义。然而,编程的深奥和复杂常常让人望而生畏。本文将从四个方面、五个方面、六个方面和七个方面对…

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修饰静态的静态方法&…

前端开发之计算机网络模型认识

上一篇👉: 前端开发之HTTP3 文章目录 网络模型1.OSI七层模型详解1.应用层2.表示层3.会话层4.传输层5.应网络层6.数据链路层7.物理层 2.TCP/IP五层协议模型3.DNS解析过程及缓存4.HTTP长连接与短连接5.HTTPS的工作原理及与HTTP区别工作原理:在HTTP基础上加…

Spring多数据源管理方案

Spring多数据源管理方案 基于Spring的AbstractRoutingDataSource实现多数据源 数据库连接配置 spring:application:name: dynamic-sourcedatasource:datasource1:jdbc-url: jdbc:mysql://localhost:3306/cloud-demo?useUnicodetrue&characterEncodingutf-8&useSSLf…

【Python高级编程】图表类型指南:何时使用折线图、散点图、柱状图和饼状图

图表类型指南:何时使用折线图、散点图、柱状图和饼状图 在数据可视化中,选择合适的图表类型对于有效传达信息至关重要。以下是四种最常见的图表类型及其用途: 折线图 折线图用于显示数据随时间或其他连续变量的变化趋势。它们对于识别趋势…

MyBatis操作数据库(一)

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

前端根据权限生成三级路由

三级菜单和后端返回数组对比获取有权限的路由 数组: //后端返回的数组 const arr1 [sale.management, sale.order, sale.detail]; //前端路由 const arr2 [{path: "/sale-manage",redirect: "/sale-manage/sale-order/sale-list",name: sale…

CentOS下的miniconda3安装

软件下载与安装 下载 [pythoningdev ~]$ wget https://repo.anaconda.com/miniconda/Miniconda3-py38_4.12.0-Linux-x86_64.sh -O /tmp/Miniconda3-py38_4.12.0-Linux-x86_64.sh --2022-08-29 10:31:06-- https://repo.anaconda.com/miniconda/Miniconda3-py38_4.12.0-Linux…

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

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

Java Mybatis plus 语法中 避免sql循环

1. 查出全部数据并进行数据筛选过滤 在一对多的情况时&#xff0c;我们想把多的对象集合set进一的里面&#xff0c;需要避免循环sql Overridepublic R<List<ExRecord>> getExRecordAll(ExRecord exRecord) {// 获取用户idInteger userId Math.toIntExact(Securit…

从位运算看海象运算符

文章目录 前言需求先找出需要多少位数使用限制赋值场景判断场景 转为one-hot编码一件小事情 前言 突然发现了Python3.8版本引入的海象运算符&#xff0c;就借着位运算的需求来看看是怎么个用法。 需求 需求是这样的&#xff0c;我有一张表&#xff0c;表中存在很多类东西&…

canvas学习

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

3.1. 马氏链-马氏链的定义和示例

马氏链的定义和示例 马氏链的定义和示例1. 马氏链的定义2. 马氏链的示例2.1. 随机游走2.2. 分支过程2.3. Ehrenfest chain2.4. 遗传模型2.5. M/G/1 队列马氏链的定义和示例 1. 马氏链的定义 对于可数状态空间的马氏链, 马氏性指的是给定当前状态, 其他过去的状态与未来的预测…

DM存储ontap系统修改管理IP

存储已配置完成在使用&#xff0c;修改管理ip不会影响生产 旧管理IP新管理IP192.0.2.1/24192.0.10.1/24192.0.2.2/24192.0.10.2/24192.0.2.3/24192.0.10.3/24 旧网关&#xff1a;192.0.2.254 新网关&#xff1a;192.0.10.254 查看现有的管理IP信息 cluster1::> network …

[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…

TS-语法介绍

1. 基本语法 变量声明 TypeScript 中的变量声明方式有 let、const 和 var&#xff0c;推荐使用 let 和 const。 let isDone: boolean false; const PI: number 3.14;函数 函数声明与 JavaScript 类似&#xff0c;但可以指定参数和返回值类型。 function add(x: number, …

ESD与EOS区别

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