【网络协议栈】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分开来写了可以看看这篇博客


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

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

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

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

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

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

相关文章

【Qt】窗口——Qt窗口的概念、常用的窗口函数、菜单栏、工具栏、状态栏、浮动窗口、对话框

文章目录 Qt窗口Qt窗口的概念菜单栏工具栏状态栏浮动窗口对话框 Qt 窗口 Qt窗口的概念 QMainWindow 类概述: QMainWindow 是一个为用户提供主窗口程序的类,它继承自 QWidget 类,并且提供了一个预定义的布局。 菜单栏 菜单栏常用属性&#xf…

C语言初阶:十.结构体基础

♥感谢您阅读本篇文章,文章内容为个人对所学内容的整理总结,欢迎大佬在评论区指点一二。♥ ♥个人主页:折枝寄北-CSDN博客折枝寄北擅长C语言初阶,等方面的知识,折枝寄北关注python,c,java,qt,c语言领域.https://blog.csdn.net/2303_80170533?…

Android Kotlin中协程详解

博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家, 👉点击跳转到教程 前言 Kotlin协程介绍: Kotlin 协程是 Kotlin 语言中的一种用于处理异步编程的机制。它提供了一…

《Python网络安全项目实战》

《Python网络安全项目实战》 项目1 Python 环境安装任务1.1 Windows上安装Python任务1.2 Ubuntu环境下安装Python 项目2 Python基础练习任务2.1 使用数据类型任务2.2 使用组合数据类型任务2.3 使用控制结构任务2.4 使用函数任务2.5 使用模块 项目3 处理文件中的数据任务3.1 读文…

雷赛L6N伺服驱动器基本参数设置——EtherCAT 总线型

1、指令脉冲设置 PA0.08代表电机转一圈,所需要的指令脉冲数,该值驱动器默认值为0,该值更改后断电重启后生效。 2、编码器反馈脉冲设置 PA0.11,代表编码器输出每转脉冲数,实际反馈的脉冲数做了4倍频处理,设…

MySql数据库中数据类型

本篇将介绍在 MySql 中的所有数据类型,其中主要分为四类:数值类型、文本和二进制类型、时间日期、String 类型。如下(图片来源:MySQL数据库): 目录如下: 目录 数值类型 1. 整数类型 2. …

【论文笔记】MLSLT: Towards Multilingual Sign Language Translation

🍎个人主页:小嗷犬的个人主页 🍊个人网站:小嗷犬的技术小站 🥭个人信条:为天地立心,为生民立命,为往圣继绝学,为万世开太平。 基本信息 标题: MLSLT: Towards Multiling…

系统架构设计师教程 第2章 2.6 计算机语言 笔记

2.6计算机语言 ★★★★☆ 2.6.1计算机语言的组成 计算机语言 (Computer Language) 是指用于人与计算机之间交流的一种语言,是人与计算机之间传递信息的媒介。 计算机语言主要由一套指令组成,指令一般包括表达式、流程控制和集合三大部分内容。 表达…

基于JSP的高校食堂食材选购管理系统【附源码】

基于JSP的高校食堂食材选购管理系统 效果如下: 系统首页界面 用户登录页面 食材信息页面 论坛交流界面 管理员登录界面 管理员功能主界面 食材信息管理界面 订单配送管理界面 用户功能主界面 商家功能主界面 司机功能主界面 研究背景 近年来互联网技术的发展使得…

新王Claude 3.5的6大应用场景

Anthropic AI深夜发布了备受期待的Claude 3.5系列更新,包括了全新升级的Claude 3.5 Sonnet和首发的Claude 3.5 Haiku。 Claude 3.5 Sonnet能够理解细微的指令和上下文,识别并纠正自身错误,还能从复杂数据中生成深入的分析和洞察。 结合最先进…

java项目之在线考试系统设计与实现(springboot)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的在线考试系统设计与实现。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 基于JavaWeb技术…

PostgreSQL C++客户端API libpqxx的使用

PostgreSQL是一个先进的、开源的、免费的、功能强大的关系型数据库,缩写版是postgres。它使用一种客户端/服务器(C/S)的模型。一次PostgreSQL会话由下列相关的进程(程序)组成: (1).一个服务器进程,它管理数据库文件、接受来自客户端应用与数据…

C++研发笔记8——C语言程序设计初阶学习笔记6

在第一部分——课前准备的学习中,我就提到了学习C语言的过程中,练习是必不可少的环节,所以本篇笔记我们来进行记录我们学习《C语言程序设计初阶》阶段的第一篇练习文章。 题目一 下面哪个不是C语言内置的数据类型: A.char B.d…

mysql5.7.44 arm 源码编译安装

一、:下载源码:mysql官网:MySQL :: MySQL Downloads #####下载mysql安装包 : 网址:https://www.mysql.com/ 可在页面下载后上传或直接下载。 官网地址首页,拉到最底部,找到社区版本下载&#xf…

财务域——财务信息化

摘要 博文探讨了企业财务信息化相关内容。首先阐述了企业以创造价值为目标,涉及业务、管理和信息三大循环。业务循环涵盖获取 / 支付、转换、销售 / 收款等环节;管理循环包含计划、执行、控制与决策;信息循环强调数据的收集、处理、存储与输…

【Linux | IO多路复用】epoll的底层原理详解

epoll 是一种高效的 I/O 多路复用机制,广泛用于 Linux 系统中,用于处理大量并发的文件描述符。它比传统的 select 和 poll 方法具有更好的性能,特别是在处理大量并发连接时。 1.epoll的设计思路 epoll是在select 出现 N 多年后才被发明的&a…

week08 zookeeper多种安装与pandas数据变换操作-new

课程1-hadoop-Zookeeper安装 Ububtu18.04安装Zookeeper3.7.1 环境与版本 这里采用的ubuntu18.04环境的基本配置为: hostname 为master 用户名为hadoop 静态IP为 192.168.100.3 网关为 192.168.100.2 防火墙已经关闭 /etc/hosts已经配置全版本下载地址&#xff1…

软考(网工)——网络安全

文章目录 🕐网络安全基础1️⃣网络安全威胁类型2️⃣网络攻击类型 🕑现代加密技术1️⃣私钥密码/对称密码体制2️⃣对称加密算法总结3️⃣公钥密码/非对称密码4️⃣混合密码5️⃣国产加密算法 - SM 系列6️⃣认证7️⃣基于公钥的认证 🕒Hash …

MYSQL全局锁、标级锁、行级锁

一、全局锁 全局锁就是对整个数据库实例加锁。 MySQL 提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FTWRL)。当你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新…

好/坏代码实例解读:图文并茂说明

我曾经在某处读到过一句话,基本上有以下内容: “现代世界许多人的生活都依赖于软件,例如控制大型商用客机飞行系统的软件,但软件开发领域大多不受监管。任何人都可以成为自学成才的软件开发人员,并且没有像其他高风险…