计算机网络—TCP协议详解:协议构成、深度解析(3)

news2024/12/28 18:02:03

 

                                        🎬慕斯主页修仙—别有洞天

                                       ♈️今日夜电波:マリンブルーの庭園—ずっと真夜中でいいのに。

                                                           0:34━━━━━━️💟──────── 3:34
                                                                🔄   ◀️   ⏸   ▶️    ☰  

                                 💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍


 

目录

流量控制

滑动窗口

滑动窗口的一些问题

拥塞控制

为什么采用指数增加的方案呢?

延时应答

面向字节流

粘包问题

TCP异常情况


流量控制

        我们都知道TCP协议的双方在通信时都是拥有自己的发送和接收缓冲区的。他们是全双工的。因此,可以一边应答一边接收数据。而在发送和应答的报文中都可以携带16位的窗口大小,这个窗口大小即表示接受缓冲区中剩余的空间大小,也就是最多还能接受多少大小的空间。接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送,就会造成丢包, 继而引起丢包重传等等一系列连锁反应.因此TCP支持根据接收端的处理能力, 来决定发送端的发送速度. 这个机制就叫做流量控制(Flow Control);
接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 "窗口大小" 字段, 通过ACK端通知发送端;

        窗口大小字段越大, 说明网络的吞吐量越高;

        接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端;

        发送端接受到这个窗口之后, 就会减慢自己的发送速度;

        如果接收端缓冲区满了, 就会将窗口置为0; 这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端
        大致的图示如下:

        思考一个问题:16位的窗口大小,16位数字最大表示65535, 那么TCP窗口最大就是65535字节么?实际上, TCP首部40字节选项中还包含了一个窗口扩大因子M, 实际窗口大小是 窗口字段的值左移 M 位;

 

滑动窗口

        前面我们提到报文是可以并发的发送的以及并发的应答的,毕竟如果只发一个然后给一个应答再接着发,这样的效率太低了。而接受方的接收能力是有限的,受着前面的16位的窗口大小影响。而滑动窗口就是用于调节发送方和接收方之间的数据传输速率,以避免网络拥塞并提高传输效率。前面我吗提到了TCP的超时重传机制,为了保证超时重传那么久必须得把发送过的报文保存起来,以便后续重传。发送方因为效率问题当然会并发的发送,那么没收到应答前这些报文是如何保存的呢?当然是在自己的发送缓冲区中啦!我们只需要将缓冲区划分为:已发生已确认、已发生未确认、待发送的三个区域就可以做到区分是否应答、保存发送过的报文以便后续超时重传的机制出发的情况。而这个已发生未确认的区域即为滑动窗口。大致的图示如下:

        实际上我们也可以将TCP中的滑动窗口理解为我们算法中常用的滑动窗口,因为他们本质上都是通过控制左边和右边的边界来控制这个窗口的!如果收到了应答的报文那么左边界会右移,如果发送了报文那么右边界也会右移。本质上就是双指针的维护作用!

滑动窗口的一些问题

        滑动窗口只能右移吗?能不能左移?实际上是不能的,因为左侧已经确认应答了,那么对于系统而言左移是没有意义的!然而,理论上讲,TCP的滑动窗口并非绝对不能左移。在某些特定的情况下,比如当接收方发现之前确认的数据有误,需要重传时,可能会涉及到窗口左移的情况。但这并不是TCP滑动窗口机制的主要操作方式,因为TCP通过序列号和确认机制来保证数据的顺序性和可靠性,而不是通过窗口的左移。

        滑动年出口移动中的大小变化?滑动窗口可以变大变小,这是根据对方的接收能力决定的,也就是他回复的16位的窗口大小来决定的!如果右边界不动,左边界一直左移,此时滑动窗口在变小,说明对面的接收缓冲区接收能力也在变小。而相反的如果左边不动右边右移,则说明对面接收缓冲区缓冲区接收能力在变大。当左边界等于有边界的时候,此时滑动窗口变为0表示对方无法接收。

        滑动窗口会越界吗?我们都知道算法中的滑动窗口会通过对什么取余来控制窗口的环形遍历,而TCP中的滑动窗口额也会想环形队列一样会回到缓冲区起点重新开始遍历。

        丢包问题的发送怎么办?例如我们并发的将1~1000、1001~2000、2001~3000、3001~4000发送给了对方。但是,对方仅仅返回了1~1000、2001~3000、3001~4000的ACK也就是说1001~2000的报文丢失了,如果是发送时丢失了,那么前面我们学到过反回来的ACK携带的确认报文只能是1001。也就是下图所示:

        那么我们的滑动窗口是如何表示的呢?如下,他会从下图位置进行移动。

        而当1001~2000补发成功并且收到ACK后,那么报文会直接返回4001的确认报文,而滑动窗口的左边界也会滑动至4000的位置!如下:

        需要注意的是:这只是客户端收到“两个”同样的“1001”的ACK的情况,因为我们一共只发了这么多的报文。但是如果我们发的报文很多,且也发生了数据包直接丢失的情况呢?

        当某一段报文段丢失之后, 发送端会一直收到 1001 这样的ACK, 就像是在提醒发送端 "我想要的是 1001"一样; 如果发送端主机连续三次收到了同样一个 "1001" 这样的应答, 就会将对应的数据 1001 - 2000 重新发送; 这个时候接收端收到了 1001 之后, 再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了, 被放到了接收端操作系统内核的接收缓冲区中; 这种机制被称为 "高速重发控制"(也叫 "快重传" )。

        这个时候你就会问了?有了快重传为什么还需要超时重传呢?看完上面的连个例子你大概就理解了!因为快重传是有条件的!只有收到三次重复的确认应答才会触发,而如果总的要收的应答就那么多,这个时候就需要超时重传了!

        如果是ACK丢失了呢?那么不会受到影响。为什么呢?还记得前面说的确认序号认为他之前的序号都是已经接受成功了的,因此滑动窗口会直接变的更上面左边界指向4001的地方一样!

拥塞控制

        当发生的数据包出现大量的丢包的问题的时候,比如:发送100个报文丢了90多个那么这就可能不是自身发送的问题了,这就是网络的问题。这种网络出现的潜在问题我们称为网络拥塞。网络拥塞会影响该网络覆盖的所有主机,所有的主机都会出现大量丢包!因此,我们需要一定的策略减清拥塞直到恢复正常。对此,可以减少发生量让网络有缓冲的时间,因为网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵. 在不清楚当前网络状态下, 贸然发送大量的数据,是很有可能引起雪上加霜的.TCP引入 慢启动 机制, 先发少量的数据, 探探路, 摸清当前的网络拥堵状态, 再决定按照多大的速度传输数据;如下图所示:


        此处引入一个概念程为拥塞窗口

        发送开始的时候, 定义拥塞窗口大小为1;每次收到一个ACK应答, 拥塞窗口加1;

        每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口;

        结合前面提到的滑动窗口,那么实际的滑动窗口大小=min(返回的16位窗口大小,拥塞窗口大小)。

        像上面这样的拥塞窗口增长速度, 是指数级别的. "慢启动" 只是指初使时慢, 但是增长速度非常快.

        为了不增长的那么快, 因此不能使拥塞窗口单纯的加倍.此处引入一个叫做慢启动的阈值

        当拥塞窗口超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长


        当TCP开始启动的时候, 慢启动阈值等于窗口最大值;在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回1;少量的丢包, 我们仅仅是触发超时重传; 大量的丢包, 我们就认为网络拥塞;当TCP通信开始后, 网络吞吐量会逐渐上升; 随着网络发生拥堵, 吞吐量会立刻下降;拥塞控制, 归根结底是TCP协议想尽可能快的把数据传输给对方, 但是又要避免给网络造成太大压力的折中方案. TCP拥塞控制这样的过程, 就好像 热恋的感觉

 

为什么采用指数增加的方案呢?

        因为这种增加的特点为前期增长慢,过了临界点后,后期增长快。这样的方案特别符合网络拥塞的情况。所以慢启动只是前期慢,但是增长的速度快!这也是后面要设置阈值的原因。

延时应答

        如何提高对方的发送效率呢?当然是在发的报文中包含更多的报文了!那么我们知道要发报文的大小是根据对面给你的回应决定的,也就说根据对方的应答报文中的窗口大小决定的!,因此要提高发送效率那么就需要返回更大的窗口,这样发送方的滑动窗口才会更大!那么如何提高呢?如果接收数据的主机立刻返回ACK应答, 这时候返回的窗口可能比较小. 假设接收端缓冲区为1M. 一次收到了500K的数据; 如果立刻应答, 返回的窗口就是500K;但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了;在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来;如果接收端稍微等一会再应答, 比如等待200ms再应答, 那么这个时候返回的窗口大小就是1M;

        一定要记得, 窗口越大, 网络吞吐量就越大, 传输效率就越高. 我们的目标是在保证网络不拥塞的情况下尽量提高传输效率;那么所有的包都可以延迟应答么? 肯定也不是;数量限制: 每隔N个包就应答一次;时间限制: 超过最大延迟时间就应答一次;具体的数量和超时时间, 依操作系统不同也有差异; 一般N取2, 超时时间取200ms;

 

面向字节流

        创建一个TCP的socket, 同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区;调用write时, 数据会先写入发送缓冲区中;如果发送的字节数太长, 会被拆分成多个TCP的数据包发出;如果发送的字节数太短, 就会先在缓冲区里等待, 等到缓冲区长度差不多了, 或者其他合适的时机发送出去;接收数据的时候, 数据也是从网卡驱动程序到达内核的接收缓冲区;然后应用程序可以调用read从接收缓冲区拿数据;另一方面, TCP的一个连接, 既有发送缓冲区, 也有接收缓冲区, 那么对于这一个连接, 既可以读数据, 也可以写数据. 这个概念叫做 全双工

        由于缓冲区的存在, TCP程序的读和写不需要一一匹配, 例如:写100个字节数据时, 可以调用一次write写100个字节, 也可以调用100次write, 每次写一个字节;读100个字节数据时, 也完全不需要考虑写的时候是怎么写的, 既可以一次read 100个字节, 也可以一次read一个字节, 重复100次;
 

 

粘包问题

        粘包问题可能由多个因素引起。首先,发送方可能由于TCP的Nagle算法或滑动窗口机制,将多个小数据包合并成一个大的数据包进行发送,从而导致粘包。其次,接收方的缓冲区处理速度可能慢于网络传输速度,使得多个数据包在缓冲区中连续存放,接收方在读取时无法准确区分各个数据包的边界。此外,网络状况的不稳定、数据包丢失以及发送方和接收方处理速度的不匹配等因素也可能导致粘包问题的发生。

        粘包问题对数据传输的准确性和可靠性造成威胁,特别是在需要精确区分数据包边界的应用场景中,如文件传输、远程控制等。因此,解决TCP粘包问题具有重要意义。

        针对TCP粘包问题,可以采取多种解决策略。归根结底就是一句话, 明确两个包之间的边界 。一种常见的方法是使用消息定界符或消息长度来标识数据包的边界。发送方在每个数据包的末尾添加特定的定界符或在开头添加表示数据长度的字段,接收方根据这些标识信息来解析数据包。另外,固定长度的消息格式也是一种解决方案,即每个数据包都使用固定大小的长度,接收方按照固定长度读取数据即可。此外,应用层协议设计也可以考虑数据包的分段和重组机制,以确保数据的完整性和准确性。
        那么对于UDP,是否存在粘包问题呢?对于UDP, 如果还没有上层交付数据, UDP的报文长度仍然在. 同时, UDP是一个一个把数据交付给应用层. 就有很明确的数据边界.站在应用层的站在应用层的角度, 使用UDP的时候, 要么收到完整的UDP报文, 要么不收. 不会出现"半个"的情况

 

TCP异常情况

进程终止: 进程终止会释放文件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别.这是因为操作系统会将进程的资源回收,当进程退出时,该进程会通过系统调用创建的链接或者文件,被操作系统自动关闭。

机器重启: 和进程终止的情况相同.

机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已经不在了, 就会进行reset. 即使没有写入操作, TCP自己也内置了一个保活定时器, 会定期询问对方是否还在. 如果对方不在, 也会把连接释放.

另外, 应用层的某些协议, 也有一些这样的检测机制. 例如HTTP长连接中, 也会定期检测对方的状态. 例如QQ, 在QQ断线之后, 也会定期尝试重新连接.

 


                       感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o! 

                                       

                                                                        给个三连再走嘛~  

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

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

相关文章

变频电源都有哪些故障?

变频电源是一种可以将市电的交流电转换为频率可调的交流电的电力电子设备,它可以根据需求调整输出电压和频率,为设备运行提供稳定可靠的电源。但是在实际使用过程中常会遇到一些故障,今天纳米软件将介绍这些故障以及解决办法。 1. 短路 短路故…

开源项目实现简单实用的股票回测

1 引言 之前,尝试做股票工具一直想做的大而全,试图抓取长期的各个维度数据,然后统计或者训练模型。想把每个细节做到完美,结果却陷入了细节之中,最后烂尾了。 最近,听到大家分享了一些关于深度学习、时序…

【xhs爬虫软件】把小红书评论comment接口封装成GUI采集工具!

用Python开发爬虫采集软件,可自动抓取小红书评论数据,并且含二级评论。 小红书的评论接口URL是: https://edith.xiaohongshu.com/api/sns/web/v2/comment/page 开发者模式分析过程: 进而封装成GUI界面软件,如下&…

【Axure教程0基础入门】05动态面板

05动态面板 1.动态面板是什么? 一个用来存放多个元件的容器(container) 其中包含多个状态(state),但同时只能显示一个 状态之间,可以通过交互动作(action)控制切换和动…

【Spring Cloud】服务容错中间件Sentinel进阶——五大规则

文章目录 Sentinel的概念和功能基本概念资源规则 重要功能流量控制熔断降级系统负载保护 SentineI 规则流控规则简单配置配置流控模式直接流控模式关联流控模式链路流控模式 配置流控效果 熔断规则慢调用比例异常比例异常数 热点规则热点规则简单使用热点规则增强使用 授权规则…

请编写函数fun,该函数的功能是:移动字符串中的内容,移动的规则如下:把第1到第m个字符,平移到字符串的最后,把第m+l到最后的字符移到字符串的前部。

本文收录于专栏:算法之翼 https://blog.csdn.net/weixin_52908342/category_10943144.html 订阅后本专栏全部文章可见。 本文含有题目的题干、解题思路、解题思路、解题代码、代码解析。本文分别包含C语言、C++、Java、Python四种语言的解法完整代码和详细的解析。 题干 请编…

Ai-WB2 系列模组SDK接入亚马逊

文章目录 前言一、准备二、亚马逊云物模型建立1. 注册亚马逊账号,登录AWS IoT控制台,[注册地址](https://aws.amazon.com/cn/)2. 创建好之后点击登录3. 创建物品以及下载证书 三、连接亚马逊云demo获取以及配置1. 下载源码2. 按照顺序执行下面指令3. 修改…

2024接口自动化测试高频面试题【建议收藏】

一、json和字典的区别? json就是一个文本、字符串;有固定的格式,格式长的像python字典和列表的组合;以key-value的键值对形式来保存数据,结构清晰,。可以说是目前互联网项目开发中最常用的一种数据交互格式…

buuctf——[CISCN2019 华北赛区 Day2 Web1]Hack World

buuctf——[CISCN2019 华北赛区 Day2 Web1]Hack World 1.根据提示,说明flag在表里 2.那就猜测存在sql注入,反手测试一波id1 3.尝试使用1--进行注释 4.直接丢进salmap里吧,不出意外多半是跑不出来 5.直接放入fuzz里进行测试 6.发现当我…

Springboot 结合PDF上传到OSS

目录 一、首先注册阿里云OSS(新用户免费使用3个月) 二、步骤 2.1 将pdf模板上传到oos 2.2 这里有pdf地址,将读写权限设置为共工读 ​编辑 三、代码 3.1 pom.xml 3.2 配置文件 3.3 oss model 3.4 配置类(不需要修改) 3.5 将配置类放入ioc容器 3.…

Linux之rocky8操作系统安装

一、rocky系统简介 CentOS宣布停止开发后,CentOS的原创始人Gregory Kurtzer在CentOS网站上发表评论宣布,他将再次启动一个项目以实现CentOS的最初目标。它的名字被选为对早期CentOS联合创始人Rocky McGaugh的致敬。rocky系统一个开源、社区拥有和管理、免…

VForm3的文件上传方式

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a…

快排非递归与计数排序

感谢大佬的光临各位,希望和大家一起进步,望得到你的三连,互三支持,一起进步 个人主页:LaNzikinh-CSDN博客 收入专栏:初阶数据结构_LaNzikinh篮子的博客-CSDN博客 文章目录 前言一.快速排序非递归二.数据结构栈与内存栈…

“电子商务”的红利还能存在多久?我想抖音回答了这个问题

哈喽~我是电商月月 互联网的发展有目共睹,网上交易,电子支付已经遍及每个人身边,两者结合,特别是电商行业,利用这个时期真的赚的盆满钵满 每年都有大批商家涌入电商这个赛道,但发展了那么多年&#xff0c…

B端界面:除了蓝色外,四条搞定清新明快的界面设计。

一、什么是清新明快风格 清新明快的设计风格是指在B端系统中使用明亮、清淡的色彩、简洁的布局和自然元素,以及轻快的动效,营造出轻松、愉悦的界面氛围。 二、哪些行业适用 这种设计风格适用于多个行业,特别是那些与创意、娱乐、健康、旅游…

Python turtle海龟绘制美国队长盾牌

使用Python中的turtle模块绘制美队盾牌 具体思路如下: 导入海龟库第1个圆:半径 200,红色填充第2个圆:半径 150,白色填充第3个圆:半径 100,红色填充第4个圆:半径 50,蓝色…

动态Web项目讲解+Demo

web流程演示 请求路径 请求路径明确要请求的是哪个servlet 请求方式 servlet含有两种请求方式:doGet和doPost doGet&doPost 返回数据就是httpResponse,返回给success 参数 包含在request当中 成功 上述流程任何一步都没出问题,就会…

Java学习笔记26(枚举和注解)

1.枚举和注解 1.1 枚举 ​ 1.枚举(enumeration) ​ 2.枚举是一组常量的集合 ​ 3.枚举属于一种特殊的类,里面只包含一组有限的特定的对象 1.枚举应用案例 ​ 1.不需要提供setXxx方法,因为枚举对象值通常为只读 ​ 2.对枚举对象/属性使用final st…

完成学校官网页面制作

<!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <title>教务系统</title> <style> .wap{ margin:0 auto; width:955px; } .top{ height:150px; padding-left:85px; …

【PCI】PCIe EP标准配置空间(十)

本文参考PCIe协议 5.0&#xff1a;https://download.csdn.net/download/zz2633105/89204842 PCIe配置空间 EP标准配置空间 Vendor ID Register (Offset 00h) PCIe设备厂商ID&#xff0c;比如Intel的Vendor ID通常是0x8086。需要注意的是&#xff0c;厂商的ID不是厂商随意定的…