【网络协议栈】Tcp协议(下)的可靠性和高效性(超时重传、快速重传、拥塞控制、流量控制)

绪论:
承接上文,上文写到Tcp协议的结构以及对tcp协议的性能优化的滑动窗口,本章我们将继续了解Tcp协议的可靠性和高效性的具体展示。后面我将继续完善网络协议栈的网络层协议敬请期待!
请添加图片描述
话不多说安全带系好,发车啦(建议电脑观看)。


OSI定制的七层网络协议栈:
在这里插入图片描述

Tcp协议可靠性和高效性:

在这里插入图片描述

1. 再次对tcp序号的理解:

发送的数据本质是从发送缓冲区中来的,而发送缓冲区本质就是个字符类的数组,所以tcp的序号本质其实就是缓冲区数组的下标!
也就有一下几点需要注意的:

  1. 序号表示的并不是数据的起始位置,而是终点位置
  2. 返回来的确认序号表示的则是下一次从那个序号开始,而不是表示为下次要发的序号
  3. 接收、发送缓冲区:char类型的数组
    在这里插入图片描述
    我们看到的数组数据的插入和删除也就是所谓的面向字节流(流在缓冲区中是不断的进出进出的类似于流动的概念)

注:

  1. tcp是不管报文的分割的,他只进行将tcp报文的报头和有效载荷(数据)的分割,将数据存进对应的缓冲区中(留给应用层使用)
  2. 在不同的tcp连接中他们tcp报文的序号是能一致的,但因为每对tcp他们的源端口和目的端口是不一样的连接都要有自己的发送和接收缓冲区,所以并不会影响

2. 超时重传

先通过图片大概了解其过程,后面通过文字描述后就会更加清晰的认识
在这里插入图片描述
上图在A->B过程中报文丢失。
在这里插入图片描述
上图是B主机返回的应答丢失
上面都是超时重传的机制发送的情况:

当A主机发送报文给B主机,当一段时间内未收到返回的应答报文,那么主机A就会再次发送报文数据给B主机。

因为有了超时重传机制,所以也会一下问题:

主机B可能会接受到同一个报文(某个报文在某处堵塞了会,导致主机A又重传,而那个报文阻塞后发送到了B主机),所以主机B还需要能够识别出那些包是重复的包并去重(此时就可以通过查看序号是否重复)

也表明:
发送方一旦把数据发出去,一段时间内已经发送的数据是不能被移除的,要被暂时保存起来(于滑动窗口有关)。

网络的状态是变化的,超时时间设置太久会影响效率,超时时间太短过于频繁的重传(去重次数增加),所以超时时间也是变化的(根据网络的状况)

超时时间的设置:
在Linux中(BSD Unix和Windows也是如此),超时以500ms为一个单位进行控制, 每次判定超时重发的超时时间都是500ms的整数倍

  1. 如果重发一次之后, 仍然得不到应答, 等待 2*500ms 后再进行重传.
  2. 如果仍然得不到应答, 等待 4*500ms 进行重传. 依次类推, 以指数形式递增.
  3. 累计到一定的重传次数, TCP认为网络或者对端主机出现异常, 强制关闭连接.

3. 连接管理

在这里插入图片描述
图中SYN_SENT(#define SYN_SENT 1)、SYN_RCVD、ESTABUSHED其实就是宏,将这几个宏对应的值填进下方结构体status中就完成了握手,三次握手是仅传递的是报头(不带数据)。
OS管理链接(先描述再组织)的本质就是结构体:

struct links
{
    string src_ip; 
    string dst_ip;
    int srcport/dstport;   
    uint64_t timestamp;
    int status;
    int urgdatatptr;//
    struct links* next;
};

所谓的链接就是双方维护的数据结构
并且需要理解:建立维护 连接 是有成本的(时间 + 空间(创建结构体))
在这里插入图片描述

4. SYN洪水问题:

Server被发送大量SYN建立连接请求(建立连接是有成本的),但并不为了真正的连接。这些假链接就会导致真链接在传输过程中被大量假链接阻挡,从而导致三次握手完成不了,也就使其无法上网。

为什么要三次握手:

在这里插入图片描述

  1. 以最小成本印证全双工(全双工:既能接收数据又能发送数据;C、S都能验证你能接收和发送数据;第一连接能证明:Server能收数据、第二次连接能证明:Client能收 发数据,第三次连接才能证明S能发数据(发出报文并且收到答应ACK才能证明能发送数据,而只要能接受到数据就表明能接受数据)),一次两次都无法完成。
  2. 奇数次握手,能保证客户端优先把链接建立好,然后服务器才建立
  3. 4次握手 + 捎带应答 = 三次握手在这里插入图片描述

四次挥手:

通过四次挥手进行连接的断开
在这里插入图片描述
他本质上来说也是能写成3次挥手的,但是因为在第二次挥手中,ACK和FIN一般不会同时发送(可以理解成断开连接是需要双方同意 确认的,所以需要分开来发送)(通俗的把三次握手看成渣男(发来就直接同意),把四次挥手看成结婚(需要双方同意))

断开连接需要 C -> S 和 S -> C(断开的本质是断开c 、 s的读写描述符也就是关闭打开文件,通过函数shutdown())
在这里插入图片描述

上图若不 close(断开连接)就会一直在 close_wait状态(而这个状态会持续较长时间),而文件描述符就没有被关闭,也就表明了连接还存在,就会持续的占用系统资源(维护的连接结构体)从而导致服务器越来越卡!(在网络应用中)

注:
查看一些配置信息(ip信息):ifconfig

在这里插入图片描述
在一台主机上,因为Tcp是全双工的所有连接一次就会有两个连接分别是S->C、C->S


5. 报文的最大存活时间(MLS)

TIME_WAIT(不认识的TIME_WAIT可以看看这篇blog)让报文消散原理:将TIME_WAIT时间设置比MLS长即可

TIME_WAIT存在的时间是:2MLS,这样就能一定保证阻塞的数据,再超时重传后不会再次发来(MLS时间就消散了,2MLS肯定没了)
(MLS是报文的最大存活时间,不同系统设定的时间是不一致的,其中centos7中MSL是60s)

查看MLS:
cat /proc/sys/net/ipv4/tcp_fin_timeout

在这里插入图片描述


6. 快(速)重传:

当发送方连续收到的ACK是同样的确认序号时,会立即将对应的报文进行补发(因为当发送方连续收到的ACK是同样的确认序号时,是不对的,本应该是收到每个发送数据对应的确认序号(序号+1),对此表示着有报文的丢失(因为正常的确认序号之前的数据都是收到的,所以丢失的报文就是发回来的确认序号后面的那个报文数据,下图返回的是1001(表示1000之前的数据是接收到的,而后面的丢失了)所以丢失的就是1001~2000的这段数据报文))
在这里插入图片描述
发送方,发送的数据发送出去,一段时间内,已经发送的数据不能被移除,会被暂时保存起来,这些暂时保存起来的数据都是在发送缓冲区的滑动窗口,只有收到对应的应答时,才会通过窗口滑动,删除指定的报文(被覆盖)

在当ACK丢了时:
在这里插入图片描述

  1. 最前面的ACK丢了时(1001),后面的ACK只要正常发送(2001),默认表示前面的数据也是被接收到了的(ACK答应报文)
  2. 而若是中间或者最后的报文丢了时,同样的转换成把他当成最前的ACK丢失,先看后面的是否有成功的(因为窗口是不断往右扫描的,当扫描到中间/最后时,它又变成了最前,这样就能套用1的方法)

7. 快(速)重传 VS 超时重传

快重传的前提连续收到三个以上的序号报文
快重传 和 超时重传他们是相互配合的:
超时重传是兜底的,快重传是提高效率的重传策略,两者相互配合

滑动窗口里面有很多可以直接发送的数据,为什么要分成多个数据段发送,不直接发一个就行了?

  1. TCP协议在传输数据时数据报文的最大消息长度(MSS)限制
  2. 避免设备处理不过来而导致的数据丢失或网络拥塞(数据从主机传送到另一个主机往往要经过路由器、网关等设备,这些设备对数据的处理能力有限。)
  3. 提高传输效率:并发多个发送多个数据段。
  4. 流量控制:接收方可以通过滑动窗口的大小来控制发送方的发送速度,从而避免网络拥塞(窗口)
  5. 差错控制:滑动窗口协议具有自动重传的功能

8. 拥塞控制:

若出现了大面积丢包,发送方就会判定是否是网络出现了问题(少量丢包采用重传是非常合理的,若大面积丢包则不能重传,就再不适合重传了,因为此时网络已经非常拥塞,再重传会损坏到网络甚至导致网络瘫痪(因为网络不止一个主机多台主机都再向该网络发送数据就可能会导致网络瘫痪))

所以tcp还考虑了网络的健康状态,即若出现大面积丢包,判断网络出现拥塞,拥塞避免算法。

TCP慢启动(拥塞算法)

先发送少量的数据,先摸清楚网络状况, 再决定按照多大的速度传输数据
在这里插入图片描述
若状态不好则先发送少量的数据,然后拥塞窗口然后再以2 ^ n 指数级的增长,前期慢 中后期快

拥塞窗口

拥塞窗口是发送数据的数值,当发送数据量超过这个拥塞窗口的值时,很大概率会网络拥塞。单次发送数据量的多少由滑动窗口决定,所以滑动窗口的大小就应该:

  • 滑动窗口大小 = min(拥塞窗口大小,对方的窗口大小)
  • win_start = ack+seq;
  • win_end = min(拥塞窗口大小,对方的窗口大小)

拥塞控制算法:慢启动 机制
防止滑动窗口一下发送大量数据到网络中,而本来网络状态就是非常拥堵的,就会导致网络状态雪上加霜。
具体如下图(拥塞窗口的增长情况)
在这里插入图片描述
采取的方法:

  1. TCP引入 慢启动 机制, 先发少量的数据, 探探路,每次收到一个ACK应答, 拥塞窗口加1;摸清当前的网络拥堵状态记录,设置拥塞窗口从1开始进行慢启动方式(只是初始慢,增长时并不慢), 再决定按照多大的速度传输数据:
  2. 每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口

  • 使用一个拥塞窗口的阈值(记为ssthresh值):当拥塞窗口增长到一定程度时到达ssthresh,由指数增长变成线性增长。
  • 在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回1
  • 网络拥塞:
    少量的丢包, 我们仅仅是触发超时重传; 大量的丢包, 我们就认为
  • 拥塞窗口必须一直在变化(探测),因为网络状态是需要一直被探测出来的

9. 延迟应答

在这里插入图片描述
作用:
通过当发送来一个报文后等待一段时间再发送的方法,让接收主机把发送来的数据给取走,从而扩大了窗口的大小,使后面再发送的数据能更大,提高了传输的效率。

其中:窗口越大, 网络吞吐量就越大, 传输效率就越高。
Tcp协议的目标就是在保证网络不拥塞的情况下尽量提高传输效率;

延迟应答一般有两种方法(也表明并不是所有的包都会延迟应答的):

  • 数量限制: 每隔N个包就延迟应答一次(如上图:一般N取2)
  • 时间限制: 超过最大延迟时间(200ms)就延迟应答一次(比如:当等待了200ms后应答一次(这样也能避免超时重传))
    延迟应答使用的情况:

假设接收端缓冲区为1M. 一次收到了500K的数据; 如果立刻应答, 返回的窗口就是500K; 但实际上可能处理端处理的速度很快, 10ms之内就500K数据从缓冲区消费掉了;在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来;如果接收端稍微等一会再应答, 比如等待200ms再应答, 那么这个时候返回的窗口大小就是1M;


10. TCP异常情况的解决方案(心跳机制)

  1. 进程终止:底层连接自动正常关闭(连接由OS管理,OS自动四次挥手)
  2. 机器重启:提示用户是否先关闭进程(然后再回到1情况)
  3. 机器掉电/网络断开
    1. 对于长时间的直接掉电/网络断开,通过服务器的心跳机制解决在这里插入图片描述
    2. 对于短时间的掉电/网络断开(网线拔了又快速的插上),此时服务器的心跳机制还没启动所以服务器就认为是正常连接的,对此当服务器给用户再次发送response包时,用户就会返回带有标志位RST的报文,表示连接错误了需要重新连接(因为对用户来说还没进行三次握手能,服务器就直接发送了报文过来)在这里插入图片描述

11. 滑动窗口

滑动窗口blog分开来写了可以看看这篇博客


本章完。预知后事如何,暂听下回分解。

如果有任何问题欢迎讨论哈!

如果觉得这篇文章对你有所帮助的话点点赞吧!

持续更新大量计算机网络细致内容,早关注不迷路。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【AI绘画】Midjourney进阶:对角线构图详解

博客主页: [小ᶻZ࿆] 本文专栏: AI绘画 | Midjourney 文章目录 💯前言💯什么是构图为什么Midjourney要使用构图 💯对角线构图特点应用场景提示词书写技巧测试 💯小结 💯前言 【AI绘画】Midjourney进阶&a…

Linux常用命令1

切换目录 cd [rootlocalhost menge]# cd /[rootlocalhost /]# cd: cd [-L|[-P [-e]] [-]] [目录] 查看当前的目录 pwd 浏览目录内容 ls ls浏览后颜色表示 白色:普通文件 蓝色:目录 红色:压缩包文件 黄色:设备文件 绿…

以 6502 为例讲讲怎么阅读 CPU 电路图

开篇 你是否曾对 CPU 的工作原理充满好奇,以及简单的晶体管又是如何组成逻辑门,进而构建出复杂的逻辑电路实现?本文将以知名的 6502 CPU 的电路图为例,介绍如何阅读 CPU 电路图,并向你演示如何从晶体管电路还原出逻辑…

.NET Core WebApi第2讲:前后端分离,Restful

动态页面:数据流动 / Web服务器 / Ajax / 前后端分离 / restful风格源栈课堂一起帮https://17bang.ren/Code/261 一、Ajax:页面可以局部刷新 1、PPT演示:使用Ajax也无法减小带宽耗用 请求第一个页面,用AJAX从服务器端加载了一个页头。 请求第…

Maven进阶——坐标、依赖、仓库

目录 1.pomxml文件 2. 坐标 2.1 坐标的概念 2.2 坐标的意义 2.3 坐标的含义 2.4 自己项目的坐标 2.5 第三方项目坐标 3. 依赖 3.1 依赖的意义 3.2 依赖的使用 3.3 第三方依赖的查找方法 3.4 依赖范围 3.5 依赖传递和可选依赖 3.5.1 依赖传递 3.5.2 依赖范围对传…

ollama 在 Linux 环境的安装

ollama 在 Linux 环境的安装 介绍 他的存在在我看来跟 docker 的很是相似,他把市面上已经存在的大语言模型集合在一个仓库中,然后通过 ollama 的方式来管理这些大语言模型 下载 # 可以直接通过 http 的方式吧对应的 shell 脚本下载下来,然…

【10天速通Navigation2】(三) :Cartographer建图算法配置:从仿真到实车,从原理到实现

前言 往期内容: 第一期:【10天速通Navigation2】(一) 框架总览和概念解释第二期:【10天速通Navigation2】(二) :ROS2gazebo阿克曼小车模型搭建-gazebo_ackermann_drive等插件的配置和说明 本教材将贯穿nav2的全部内容&#xff0c…

【Android】Kotlin教程(4)

文章目录 1.field2.计算属性3.主构造函数4.次构造函数5.默认参数6.初始化块7.初始化顺序7.延迟初始化lateinit8.惰性初始化 1.field field 关键字通常与属性的自定义 getter 和 setter 一起使用。当你需要为一个属性提供自定义的行为时,可以使用 field 来访问或设置…

Visual Studio2022 Profile 工具使用

本篇研究下Visual Studio自带的性能分析工具,针对C代码,基于Visual Studio2022 文章目录 CPU使用率检测并发可视化工具使用率视图线程视图内核视图并发可视化工具SDK 参考资料 CPU使用率 对于CPU密集型程序,我们可以通过分析程序的CPU使用率…

【MySQL】MySQL数据库中密码加密和查询的解决方案

本篇博客是为了记录自己在遇到password函数无法生效时的解决方案。通过使用AES_ENCRYPT(str,key)和AES_DECRYPT(str,key)进行加密和解密。 一、问题 自己想创建一个user表,user表中有一个password属性列,自己想对密码进行加密后再存入数据库&#xff0c…

基于JAVA+SpringBoot+Vue的华府便利店信息管理系统

基于JAVASpringBootVue的华府便利店信息管理系统 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末附源码下载链接&#x1f3…

GCC 简介

Linux 中的编译器 GCC 的编译原理和使用详解 GCC 简介 GCC(GNU Compiler Collection)是一套由 GNU 开发的编程语言编译器,它支持多种编程语言,包括 C、C、Objective-C、Fortran、Ada 和 Go 等。GCC 是一个开源的工具集&#xff…

STM32F103C8T6 IO 操作

1.开启相关时钟 在 STM32 微控制器中,开启 GPIO 端口的时钟是确保 IO 口可以正常工作的第一步。 查找 RCC 寄存器使能时钟 在 STM32 中,时钟控制的寄存器通常位于 RCC (Reset and Clock Control) 模块中。不同的 STM32 系列(如 STM32F1、STM…

vue3+vite 部署npm 包

公司需要所以研究了一下怎么部署安装,比较简单 先下载个vue项目 不用安准路由,pinna 啥的,只需要一个最简单的模版 删掉App.vue 中的其它组件 npm create vuelatest 开始写自定义组件 新建一个el-text 组件, name是重点,vue3中…

《Python游戏编程入门》注-第3章3

《Python游戏编程入门》的“3.2.4 Mad Lib”中介绍了一个名为“Mad Lib”游戏的编写方法。 1 游戏玩法 “Mad Lib”游戏由玩家根据提示输入一些信息,例如男人姓名、女人姓名、喜欢的食物以及太空船的名字等。游戏根据玩家输入的信息编写出一个故事,如图…

洛谷 P1226:【模板】快速幂

【题目来源】https://www.luogu.com.cn/problem/P1226【题目描述】 给你三个整数 a,b,p,求 a^b mod p。【输入格式】 输入只有一行三个整数,分别代表 a,b,p。【输出格式】 输出一行一个字符串 a^b mod ps&a…

Centos7快速重置root密码

1、重新启动Centos7,5秒内按向下方向键,使其停留在开机界面,如下图。 2、按’e’键,进入如下界面,移动向下方向键至“linux16”开头的行。然后按向右的方向键移动,找到“ro”并将其修改为“rw init/sysroot/bin/bash…

编写一个简单的Iinput_dev框架

往期内容 本专栏往期内容: input子系统的框架和重要数据结构详解-CSDN博客input device和input handler的注册以及匹配过程解析-CSDN博客input device和input handler的注册以及匹配过程解析-CSDN博客 I2C子系统专栏: 专栏地址:IIC子系统_憧憬…

使用 NumPy 和 Matplotlib 进行高级数据可视化:实践指南

使用 NumPy 和 Matplotlib 进行高级数据可视化:实践指南 数据科学和工程实践中,NumPy 和 Matplotlib 是强大的组合工具。本文将进一步展示如何借助这两个库进行更复杂的可视化任务,例如创建多曲线、叠加图、动态可视化等场景。 一、环境准备…

Crowd Counting 系列NO4.—SwitchCNN(CVPR 2017)网络复现

文章目录 引言简介环境配置1、numpy 安装2、matplotlib 安装3、cv2 安装,即opencv-python安装4、scipy 安装5、theano安装7、flip_filters不再支持 数据问题密度图生成注意 引言 SwitchCNN是我看的比较早的一篇多列密集计数网络了,但是其网络实现因各种…