Linux网络原理及编程(6)——第十六节 TCP可靠性保证的原理

简介: 你在应用层上想要发送一个信息,但是我在底层可能是通过发送多次、甚至有触发了超时重传等等。而站在用户的角度呢,你不用去管它,我传输层不管怎么发,反正最终把你的数据发出去就可以了。也就是说,应用层的传输和底层传输层的并不是一对一、一一对应的关系。

TCP中采用了许许多多的机制,来保证网络传输过程当中数据的可靠性的问题。这里的可靠可以广义一点来理解。它几乎涉及到了方方面面。我们现在就挑选一些最最重要的机制来进行讲解。


1、确认应答机制

image.png

如图,我们在之前的TCP协议的特性中实际上也详细地说到过。


对于某一个报文,其发送出去之后,返回的报文需要携带一个ACK的应答标志。这里就点出其有这样一个性质,不再做过多赘述。


2、超时重传机制

image.png

主机A发送数据给B之后, 可能因为网络拥堵等原因, 数据无法到达主机B;


如果主机A在一个特定时间间隔内没有收到B发来的确认应答, 就会进行重发。


但是, 主机A未收到B发来的确认应答, 也可能是因为ACK丢失了



因此主机B会收到很多重复数据. 那么TCP协议需要能够识别出那些包是重复的包, 并且把重复的丢弃掉.


这时候我们可以利用前面提到的序列号, 就可以很容易做到去重的效果(这是序号的第二个作用,也是可靠性的体现)


【超时的时间间隔】

最理想的情况下, 找到一个最小的时间, 保证 "确认应答一定能在这个时间内返回".


但是这个时间的长短, 随着网络环境的不同, 是有差异的.


如果超时时间设的太长, 会影响整体的重传效率;


如果超时时间设的太短, 有可能会频繁发送重复的包;


需要指出的是,应用层不需要关心通信细节。


比如,你在应用层上想要发送一个信息,但是我在底层可能是通过发送多次、甚至有触发了超时重传等等。而站在用户的角度呢,你不用去管它,我传输层不管怎么发,反正最终把你的数据发出去就可以了。也就是说,应用层的传输和底层传输层的并不是一对一、一一对应的关系。


就是说,我们这里所说的关系,都是在传输层上的,都是操作系统、网络等帮助我们做好的。


快重传

对于超时重传机制,我们可以再细分两种情况来进行讨论一下:


情况一:

image.png

数据包已经抵达, ACK被丢了。这种情况下, 部分ACK丢了并不要紧, 因为可以通过后续的ACK进行确认。


这种情况没有什么好说的。


情况二:

image.png

如上图,比如数据包就直接丢了。


当某一段报文段丢失之后, 发送端会一直收到 1001 这样的ACK, 就像是在提醒发送端 "我想要的是 1001"一样;


如果发送端主机连续三次收到了同样一个 "1001" 这样的应答, 就会将对应的数据 1001 - 2000 重新发送;


这个时候接收端收到了 1001 之后, 再次返回的ACK就是7001了


(因为2001 - 7000)接收端其实之前就已经收到了, 被放到了接收端操作系统内核的接收缓冲区中


这种机制被称为 "高速重发控制"(也叫 "快重传")


(注意,在一般情况下,其实没有这种机制,我们也会重传,但其为超时重传)


一般情况下,超时重传用来兜底(比如我的窗口大小只有1个报文)


3、滑动窗口

刚才我们讨论了确认应答策略, 对每一个发送的数据段, 都要给一个ACK确认应答. 收到ACK后再发送下一个数据段。这种方式叫做串性发送消息。


这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候


既然这样一发一收的方式性能较低, 那么我们一次发送多条数据, 就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了).如下图

image.png


这样做的好处,不仅仅是提高了效率,而且能容忍部分ACK的丢失


那为啥我们不一下子把数据全部发过去呢?


原因很简单,我们发送的数据的多少,同时还要受到对方接受能力的影响。(这个指双方的窗口(接受缓冲区)大小,并且在三次握手时就已经协商完毕)


窗口大小指的是暂时无需等待确认应答而可以继续发送数据的最大值. 上图的窗口大小就是4000个字节(四个段)


那滑动窗口是什么捏?


对于一个发送缓冲区,我们将其分成三个部分:


滑动窗口之前、滑动窗口里、滑动窗口之后


滑动窗口之前的数据是属于已经发送并且已经收到ACK的数据。(收到之后就删掉了)


滑动窗口之后的数据是属于尚未发送的数据。


滑动窗口里的:可以(已经)发送或者未收到ACK的数据。


滑动窗口的巧妙之处就在于,其一旦收到某一个数据的ACK,其前面的数据就表示都受到了,即滑动窗口可以的尾部可以直接滑动到该数据之处。(即我收到谁,我就可以认为之前的都收到了)


滑动窗口是属于发送缓冲区的一部分! 有多大呢? <=对方的接收缓冲区的大小。


如何理解滑动窗口?

image.png


定义两个指针,一个left,一个right。就不断让left和right加数值就可以实现滑动窗口的移动了。


为了避免其过大超出缓冲区的范围,我们就将其设计为环形的,即可以模上一个数值。


我们之前在上层的接口Send()实际上就是在往缓冲区里写。(往滑动窗口后面写)


(在后面的OJ题中,我们也将会用到滑动窗口呦)


如果缓冲区满了,在上层的体现就是send()阻塞。


本质上,发送缓冲区也就是一种生产者消费者模型。


窗口越大, 则网络的吞吐率就越高;即滑动窗口的大小是可变的(可变大、变小)


4、流量控制

微信图片_20221211143616.png

接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 "窗口大小" 字段, 通过ACK端通知发送端;


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


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


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


如果接收端缓冲区满了, 就会将窗口置为0; 这时发送方不再发送数据, 但是需要定期发送一个窗口探测数


据段(可能会携带PSH标志位), 使接收端把窗口大小告诉发送端。与此同时,接收方在有空间之后也需要给发送方发送窗口更新通知。



如果就是不取,那是应用层的BUG了,这个锅就是不OS传输层的了。


所以,调用recv本质上就是将数据从接收缓冲区中读走。


5、拥塞控制

那有没有要考虑是网络的问题呢?

image.png


少量的丢包, 我们仅仅是触发超时重传; 大量的丢包, 我们就认为网络拥塞;


当TCP通信开始后, 网络吞吐量会逐渐上升; 随着网络发生拥堵, 吞吐量会立刻下降;


拥塞控制, 归根结底是TCP协议想尽可能快的把数据传输给对方, 但是又要避免给网络造成太大压力的折中方案.


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


它的作用是:你的数据发送的速率不能超过我拥塞窗口的大小,不然就可能会造成拥塞。



发送开始的时候, 定义拥塞窗口大小为1;


每次收到一个ACK应答, 拥塞窗口加1;


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


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


为了不增长的那么快, 因此不能使拥塞窗口单纯的加倍.


此处引入一个叫做慢启动的阈值,当拥塞窗口超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长(通常是拥塞窗口的1/2)


(1)当TCP开始启动的时候, 慢启动阈值等于窗口最大值;


(2)tcp认为,当它重传了一个报文段即触发了超时重传机制后,其就会认为网络拥塞,这个时候,其会将慢启动阈值记为cwnd的一半,cwnd置为1。


(3)而当其触发的是快速重传机制的时候(即收到了三个或者以上相同的ACK),其会将慢启动阈值设置为cwmd的一般,然后将cwnd设置为慢启动阈值的值(或者加三,加三的原因表明是 有三个老的数据报离开了网络)然后重传丢失的报文段,这个时候,如果收到的是该报文段的ACK,那么拥塞窗口+1;如果收到的是新的报文段的ACK,那么证明网络已经回复,进入拥塞避免的线性增长阶段。



TCP拥塞控制这样的过程, 就好像 热恋的感觉


6、延迟应答

如果接收数据的主机立刻返回ACK应答, 这时候返回的窗口可能比较小.



假设接收端缓冲区为1M. 一次收到了500K的数据; 如果立刻应答, 返回的窗口就是500K;


但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了;


在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来;


如果接收端稍微等一会再应答, 比如等待200ms再应答, 那么这个时候返回的窗口大小就是1M;



就是说,先等一会,等用户从我的缓冲区中取走一点,然后我给你返回的接受缓冲区就会更大。


一定要记得, 窗口越大, 网络吞吐量就越大, 传输效率就越高. 我们的目标是在保证网络不拥塞的情况下尽量提高传输


效率;


那么所有的包都可以延迟应答么? 肯定也不是;


数量限制: 每隔N个包就应答一次;


时间限制: 超过最大延迟时间就应答一次;


具体的数量和超时时间, 依操作系统不同也有差异; 一般N取2, 超时时间取200ms


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
7天前
|
机器学习/深度学习 算法 PyTorch
深度强化学习中SAC算法:数学原理、网络架构及其PyTorch实现
软演员-评论家算法(Soft Actor-Critic, SAC)是深度强化学习领域的重要进展,基于最大熵框架优化策略,在探索与利用之间实现动态平衡。SAC通过双Q网络设计和自适应温度参数,提升了训练稳定性和样本效率。本文详细解析了SAC的数学原理、网络架构及PyTorch实现,涵盖演员网络的动作采样与对数概率计算、评论家网络的Q值估计及其损失函数,并介绍了完整的SAC智能体实现流程。SAC在连续动作空间中表现出色,具有高样本效率和稳定的训练过程,适合实际应用场景。
36 7
深度强化学习中SAC算法:数学原理、网络架构及其PyTorch实现
|
9天前
|
Ubuntu Linux 开发者
Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统
使用上述U-Boot命令配置并启动嵌入式设备。如果配置正确,设备将通过TFTP加载内核和设备树,并通过NFS挂载根文件系统。
49 15
|
14天前
|
Ubuntu Unix Linux
Linux网络文件系统NFS:配置与管理指南
NFS 是 Linux 系统中常用的网络文件系统协议,通过配置和管理 NFS,可以实现跨网络的文件共享。本文详细介绍了 NFS 的安装、配置、管理和常见问题的解决方法,希望对您的工作有所帮助。通过正确配置和优化 NFS,可以显著提高文件共享的效率和安全性。
109 7
|
16天前
|
前端开发 网络协议 安全
【网络原理】——HTTP协议、fiddler抓包
HTTP超文本传输,HTML,fiddler抓包,URL,urlencode,HTTP首行方法,GET方法,POST方法
|
16天前
|
域名解析 网络协议 关系型数据库
【网络原理】——带你认识IP~(长文~实在不知道取啥标题了)
IP协议详解,IP协议管理地址(NAT机制),IP地址分类、组成、特殊IP地址,MAC地址,数据帧格式,DNS域名解析系统
|
16天前
|
存储 JSON 缓存
【网络原理】——HTTP请求头中的属性
HTTP请求头,HOST、Content-Agent、Content-Type、User-Agent、Referer、Cookie。
|
23天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
91 13
|
16天前
|
安全 算法 网络协议
【网络原理】——图解HTTPS如何加密(通俗简单易懂)
HTTPS加密过程,明文,密文,密钥,对称加密,非对称加密,公钥和私钥,证书加密
|
16天前
|
XML JSON 网络协议
【网络原理】——拥塞控制,延时/捎带应答,面向字节流,异常情况
拥塞控制,延时应答,捎带应答,面向字节流(粘包问题),异常情况(心跳包)
|
18天前
|
网络协议 安全 网络安全
探索网络模型与协议:从OSI到HTTPs的原理解析
OSI七层网络模型和TCP/IP四层模型是理解和设计计算机网络的框架。OSI模型包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,而TCP/IP模型则简化为链路层、网络层、传输层和 HTTPS协议基于HTTP并通过TLS/SSL加密数据,确保安全传输。其连接过程涉及TCP三次握手、SSL证书验证、对称密钥交换等步骤,以保障通信的安全性和完整性。数字信封技术使用非对称加密和数字证书确保数据的机密性和身份认证。 浏览器通过Https访问网站的过程包括输入网址、DNS解析、建立TCP连接、发送HTTPS请求、接收响应、验证证书和解析网页内容等步骤,确保用户与服务器之间的安全通信。
74 1