【网络协议】TCP协议常用机制——延迟应答、捎带应答、面向字节流、异常处理,保姆级详解,建议收藏

news2024/11/25 10:56:15

💐个人主页:初晴~

📚相关专栏:计算机网络那些事


        前几篇文章,博主带大家梳理了一下TCP协议的几个核心机制,比如保证可靠性的 确认应答、超时重传 机制,和提高传输效率的 滑动窗口及其相关优化机制。除此之外,TCP还有一些非常重要的核心机制,就让博主在本篇文章带着大家学习一下吧

一、延迟应答

TCP协议中的延时应答(Delayed Acknowledgment)机制是一种优化技术,旨在减少网络中的确认(ACK)消息数量,从而提高网络带宽利用率和减少网络拥塞

试想一下,如果接收端在收到数据时就立马返回ACK应答可能会出现什么问题?

这时返回的窗口可能会比较小

  • 假设接收端缓冲区1M,⼀次收到了500K的数据,如果⽴刻应答,返回的窗⼝就是500K
  • 但实际上可能处理端处理的速度很快,10ms之内就把500K数据从缓冲区消费掉了
  • 在这种情况下,接收端处理还远没有达到⾃⼰的极限,即使窗⼝再放⼤⼀些, 也能处理过来
  • 如果接收端稍微等⼀会再应答,⽐如等待200ms再应答,那么这个时候返回的窗⼝⼤⼩就是1M

主要原理是接收端接收数据的时候,应用程序也在源源不断地消费接受缓冲区内的数据。

在收到数据时,先等一小会儿,缓冲区内的数据可能就会被消费而少掉很多,此时再返回给发送端 ACK时,返回的窗口大小就大概率会比立即返回更大。

窗口越大,网络吞吐量就越大传输效率也越高。因此延迟应答在一定程度上就能提高网络传输的效率。

但难道能一直延迟下去吗?延迟的时间过久也是会导致接受缓冲区爆满,引发丢包等一系列问题的。因此TCP会对延迟时间做出一些限制

  • 数量限制:每隔N个包就应答⼀次
  • 时间限制:超过最⼤延迟时间就应答⼀次
具体的数量和超时时间,依操作系统不同也有差异。⼀般N取2,超时时间取200ms

这样就能很好地控制应答报文的返回密度,在不影响传输可靠性的条件下,尽可能提高网络传输的效率


二、捎带应答

延迟应答 的基础上,我们发现,实际网络通信中,大多数情况下都是“一问一答”的形式:

  • ack ,是系统内核返回的,在收到请求后就立即返回ack
  • 响应,是应用程序返回的,在代码中,根据请求计算得到响应,然后再返回给发送端

正常情况下,ack与响应 返回的时机不同,无法进行合并。

但别忘了,ack涉及“延时应答”机制,会ack返回时间推迟。这一推迟,ack 就有机会等到 响应 报文生成的时候了,于是就可以再发送响应的时候,捎带上ack数据。

就好比说 客⼾端 给服务器说了 "How are you",服务器也会给客⼾端回⼀个 "Fine, thank you",而这个时候ack就等了一会儿,搭上顺风车,和服务器回应的 "Fine, thank you" 一起返回给客户端

还记得之前在 TCP协议“三次握手,四次挥手” 一文中我们研究过的四次挥手吗?

当时我们介绍过,ack是系统内核返回的,fin是应用程序返回的,理论上来说这俩发送时机并不同,是无法合并的。这也是“四次挥手”说法的由来。

但是,在延时应答的机制下,ack的返回时间可能会推迟,就有可能会和 FIN 合并,一起返回了。这时,“四次挥手” 就变成 “三次挥手” 了。

 之所以ack可以和响应报文合并,是因为 ack 报文本身不需要载荷,只需在报头中将 ack字段设为“1”,接着设置好窗口大小、确认序号即可。这并不会与正常的响应报文产生冲突

 


三、面向字节流

创建⼀个TCP的socket, 同时在内核中创建⼀个 发送缓冲区 和⼀个 接收缓冲区;
  • 调⽤write时,数据会先写⼊发送缓冲区
  • 如果发送的字节数太⻓,会被拆分成多个TCP的数据包发出
  • 如果发送的字节数太短,就会先在发送缓冲区⾥等待,等到缓冲区⻓度差不多了,或者其他合适的时机发送出去
  • 接收数据的时候,数据也是从⽹卡驱动程序到达内核的接收缓冲区
  • 然后应⽤程序可以调⽤read接收缓冲区拿数据
  • 另⼀⽅⾯,TCP的⼀个连接,既有发送缓冲区,也有接收缓冲区

对于这⼀个连接,既可以读数据也可以写数据。这个概念叫做 全双⼯

由于缓冲区的存在,TCP程序的读和写不需要⼀一匹配,例如:
读写100个字节的数据时:
1、可以一次读写一个字节,分 100 次读写
2、可以一次读写十个字节,分 10 次读写
3、可以一次读写50个字节,分 2 次读写
4、可以一次读写100个字节,一次读写完
……

这样读写虽然十分自由,但也会带来一些问题。相比于面向数据报的传输方式,通过面向字节流的方式每次传输的界限没有那么分明了。容易导致粘包问题:

应用层数据包在TCP的接收缓冲区内连成一片,粘在一起

站在应⽤层的⻆度, 看到的只是⼀串连续的字节数据。当应用程序需要读取接收缓冲区内的数据时,由于TCP是面向字节流的,因此缓冲区内数据怎么读都有可能。

可能会读出 a,a,a,b,b,b,c,c,c

也可能读出 aaa,bbb,ccc

还可能读出 aaabbbccc

……

这样肯定是不利于正确读取数据包意义的。想要解决粘包问题,关键就是要明确“包之间的边界”

  • 方案一:指定分隔符

比如我们可以约定,请求响应都以 “\n” 结尾。这样在发送读取的时候都用 “\n” 作为分隔符,每当读写到 “\n” 时,就意味着一个数据包已经结束了,应用端就可以正常对这个数据包进行解析了。

不过,采用这种方案时一定要注意避免数据内容的正文中也会出现分隔符。比如采用ASCII中靠前的目前已不再使用的一些“控制字符”作为分隔符就比较合适。

常见的几种协议有xml、yml、json等,一般适用于文本类的数据的传输。

  • 方案二:指定数据的长度

比如,约定在每个应用层数据包的开头2~4个字节,表示数据包的长度

UDP协议采用的就是这种方案。因此UDP传输是不会出现粘包问题的


四、异常情况处理

现实的网络通信中,不是每一次通信都能够正常完成“四次挥手”断开连接的,可能会遇到各种各样的异常情况。

1、进程崩溃

进程崩溃,听起来很严重,实际上操作系统会做好善后。当进程崩溃时,进程中的PCB就会被回收了,PCB中的⽂件描述符中的所有文件都会被操作系统自动关闭,仍然可以发送FIN。和正常关闭没有什么区别

2、主机关机(正常关机)

正常点击关机键关机时,操作系统会先终止所有进程,同时也会触发“四次挥手”机制。而这时就可能会出现两种情况:

(1)四次挥手完成后,关机才真正完成

这种情况不会有什么问题,通信会正常断开

(2)四次挥手还没有挥完,就已经关机完毕了

这时就有可能收不到 B 发来的 FIN 请求,也就无法像其返回ack,而 B 并不知道 A 已经关机了,接收不到 ack 就会导致四次挥手迟迟不能完成,通信也就无法正常断开了。

 由于 B 接收不到 A 的ACK应答报文,等待一定时间就会触发“超时重传”机制重新发送 FIN报文。当 B 重传一定次数还没有响应时,就会主动断开连接(把保存的 A 的信息删掉了)。虽然过程有些曲折,但最终也能成功让通信断开

3、主机断电(异常关机)

(1)接收方断电

 这时 A 给 B 发送数据,就不会再返回 ACK 了。

A 就会触发超时重传,当多次重传都没有得到 ACK 时,A就会尝试重置连接(reset)。如果重置操作也没有 ACK,A 就会单方面的释放连接(把 B 的信息删掉)

(2)发送方断电

 A  发着发着没声了。在 B 的视角看来,并不确定 A 是终止了,还是说就是这段时间没有请求而已。此时,B 就会给 A 发送一个数据包,询问 A 是否还在。

如果发了探测报文后,A 返回了 ACK,就说明 A 只是暂时没有请求而已。但如果连续发了多个探测报文,A 都没有返回 ACK,就可以认为 A 是异常终止了。就会单方面释放连接。

TCP内置了⼀个保活定时器,会定时发送这样的探测报文。因为这样的报文是用来探测对方“生死”的,因此也会被称之为“心跳包”

4、网线断开

与主机断电类似。只不过是通信双方都感知不到对方的存在了。

  • A 的视角:A 收不到 ACK ,触发多次超时重传,然后尝试重置连接,最后会单方面释放连接
  • B的视角:A 忽然没有反应了。发多次心跳包也没有回应,最后也会单方面释放连接

这样,虽然过程曲折,但最后的结果还是成功让双方断开连接了。这样的处理还是能够让人接受的

总结


那么本篇文章就到此为止了,如果觉得这篇文章对你有帮助的话,可以点一下关注和点赞来支持作者哦。如果有什么讲的不对的地方欢迎在评论区指出,希望能够和你们一起进步✊

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

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

相关文章

C++ Builder XE12关于KonopkaControls与TMS VCL UI Pack组件的安装

1、先打开open project,选中安装的组件工程,并打开。 2、在option中设置 3、点击编译并进行安装install

洞察AI趋势:智享AI直播,打造专属你的数字化直播AIGC系统!

洞察AI趋势:智享AI直播,打造专属你的数字化直播AIGC系统! 在当今这个日新月异的数字时代,人工智能(AI)已不再是遥不可及的未来科技,而是正深刻改变着我们生活、工作的每一个角落。其中&#xf…

幽默视频下载网站推荐

在快节奏的生活中,搞笑视频无疑是缓解压力的良药,不论是自制搞笑视频还是寻找素材来增添创作的趣味性,找到合适的视频素材至关重要。幸运的是,网络上有许多优秀的网站能够满足这一需求。以下是8个适合下载幽默搞笑视频素材的网站&…

华为 静态路由和bfd 侦测的实验

实验要求 sw1 上业务地址192.168.1.1/24 SW3 业务地址192.168.2.1/24 正常情况下走主链路,不正常的情况下走备份链路 2 配置 这是基本地址配置 开启了bfd 本端地址为 10.1.1.1 对端地址是10.1.1.2 关键是discrimination 分辨参数 …

静态路由和nqa 联动实验

nqa 配置 1 test 断端口 很明显是切换到备机上了

Word中如何删除表格下一页的空白页

Reference: [1] Word空白页怎么都删除不掉?用这6个方法随便删! - 知乎 (zhihu.com)

前端埋点学习

前端埋点 前端数据埋点是在前端页面中通过代码的方式手机用户行为数据和页面性能的过程,通过在页面中插入指定的代码,实现实时监控用户在页面上的操作行为。 通常包括一下事件 定义事件: 定义需要手机的数据事件,如点击,浏览等添…

基于Docker的FRP内网穿透部署

服务器搭建(FRPS) 创建配置文件 # 创建存放目录 sudo mkdir /etc/frp # 创建frps.ini文件 nano /etc/frp/frps.ini frps.ini内容如下: [common] # 监听端口 bind_port 7000 # 面板端口 dashboard_port 7500 # 登录面板账号设置 dashboa…

【进阶OpenCV】 (9)--摄像头操作--->答题卡识别改分项目

文章目录 项目:答题卡识别改分1. 图片预处理2. 描绘轮廓3. 轮廓近似4. 透视变换5. 阈值处理6. 找每一个圆圈轮廓7. 将每一个圆圈轮廓排序8. 找寻所填答案,比对正确答案8.1 思路8.2 图解8.3 代码体现 9. 计算正确率 总结 项目:答题卡识别改分 …

数论与同余 - 离散数学系列(七)

目录 1. 整数的性质 整除与因数 最大公约数与最小公倍数 2. 欧几里得算法 算法步骤 3. 模运算与同余 模运算 同余关系 同余的性质 4. 数论在密码学中的应用 RSA 加密算法 5. 实际应用场景 1. 数字签名 2. 哈希函数与数据完整性 3. 密钥交换 6. 例题与练习 例题…

Java:方法详解

目录 一.什么是方法(method) 二.方法定义 三.方法中实参和形参的关系 四.方法重载 五.递归 一.什么是方法(method) 方法就是一个代码片段,再C语言中我们曾经学过一个类似的方式——函数,他们都是将具有独立功能的代码组织成一个整体,形成…

论文阅读 BLIP-2

Bootstrapping Language-Image Pre-training with Frozen Image Encoders and Large Language Models 使用冻结的图像编码器和大型语言模型进行语言-图像预训练的引导 BLIP-2 通过一个轻量级的查询变换器弥合了模态之间的差距。 Querying Transformer 第一阶段通过冻结的图像编…

高纯PGME和PGMEA市场规模:2023年全球市场规模为6.43亿美元

研究对象:高纯PGME和PGMEA行业 高纯PGME(丙二醇甲醚)和PGMEA(丙二醇甲醚醋酸酯)是重要的有机溶剂,广泛应用于半导体和面板制造领域,尤其是在光刻胶和清洗剂中。高纯度的PGME和PGMEA对于确保电子…

软件测试面试题600多条及答案

这些问题都是软件测试领域常见的面试问题,以下是一些可能的答案: 什么是软件测试? 软件测试是一系列活动,旨在评估软件产品的质量和性能,以确保它符合规定的需求和标准。它包括执行程序或系统以验证其满足规定需求的过…

javaWeb-Mybatis操作

1.删除 2.新增 注意: 1. 使用对象来接收 2.插入的数据的名字,要和对象的属性名一致 3.新增(主键返回) 4.更新 5.查询(根据id查询) 会把查询到的数据映射到字段上。 6.查询(条件查询) %张%-->%${name}%

前端必知必会-Bootstrap 5 工具提示Tooltip

文章目录 Bootstrap 5 工具提示如何创建工具提示定位工具提示 总结 Bootstrap 5 工具提示 工具提示组件是一个小的弹出框,当用户将鼠标指针移到元素上时会出现: 如何创建工具提示 要创建工具提示,请将 data-bs-toggle“tooltip” 属性添加…

人工智能长期记忆的新突破:HippoRAG的创新框架

人工智能咨询培训老师叶梓 转载标明出处 大模型(LLMs)在预训练后,如何有效地整合大量新经验,同时避免灾难性遗忘,一直是人工智能领域的难题。尽管已有的检索增强生成(RAG)方法为LLMs提供了长期…

云轴科技ZStack入选信通院《高质量数字化转型产品及服务全景图》AI大模型图谱

近日,由中国互联网协会中小企业发展工作委员会主办的“2024大模型数字生态发展大会暨铸基计划年中会议”在北京成功召开。会上发布了中国信通院在大模型数字化等领域的多项工作成果,其中重点发布了《高质量数字化转型产品及服务全景图(2024上…

解决重写QSilder::sliderPress后点击位置与滑块显示位置不一样的问题

如下代码所示,我是用的是事件过滤器,也可以重写QSlider。 bool KuGouApp::eventFilter(QObject *watched, QEvent *event) {if(watched ui->progressSlider) {if (event->type()QEvent::MouseButtonPress) //判断类型{auto mouseEvent…

【封装案例】点和圆的关系

文章目录 前言1、point.h文件2、circle.h文件3、point.cpp文件4、circle.cpp文件5、主函数和全局函数6、测试 前言 本篇主要是用C实现一个判断点和圆关系的程序。 思路:已知点和圆心的坐标,通过比较两点间的距离和圆半径的大小,判断两者的关…