网络编程(12): TCP重传、滑动窗口、流量控制、拥塞控制

1、TCP重传机制

通过序列号和确认号确保可靠传输,当发送端发送数据给接收到,接收端会返回一个确认号,表示收到消息了

  • 超时重传:没有在指定时间内收到ACK报文
    • 超时重传的两种可能:数据包丢失确认包丢失
    • 超时重传时间RTO:
      • RTO较大:重发就变慢了,丢包之后需要半天才能重发,效率低
      • RTO较小:可能没有丢包,还在等待ACK过程中,就重发了,会导致网络拥塞,进而导致更多的超时重发
      • 所以RTO需要略大于报文往返的时间RTT(数据发送到接收到ACK的时间差)
    • 由于网络波动问题,RTT可能不是固定的,所以RTO对应也不是固定的
    • 一般超时重传一次,下一次超时重传的间隔会加倍,避免网络环境差的频繁发送
  • 快速重传
    • 超时重传的问题:重传周期可能很长(时间会加倍),快速重传可以解决这个问题,以数据为驱动作为重传
    • 发送了数据包seq1~seq5,
      • 发送端发送seq1,接收端回复ack=2,表示接收到包1
      • seq2丢失
      • 发送端连续发送seq3~seq5,接收端会重复返回ack=2
      • 连续三次ack=2,触发快速重传,重复seq2
      • 由于接收到了seq3~seq5,发送端会返回ack=6
    • 快速重传只解决了超时问题,但是还有一个问题:重传的时候重传一个还是所有数据包
    • 因为如果只重传一个,当有两个数据包丢失的时候,需要判断两次返回的ack(三次重复),来进行单包重传,效率低
    • 如果重传所有,就会有多余的包被重新发送,无用功
  • SACK:选择性确认,可以知道哪些数据丢失了
    • 需要TCP头部选项字段中,添加一个SACK,可以将已接收到的数据的信息发送给发送方,发送方就知道了哪些数据丢失了,从而只发送丢失的数据
    • 在快速重传的基础上,发送方收到三次相同的ack报文,触发快速重传机制,通过SACK信息可以知道哪段数据丢失了,只对丢失的数据重传
  • D-SACK:通过SACK告诉发送端哪些数据被重复接收了
    • 可以让发送端知道是包丢失,还是ACK包丢失了
    • 可以知道发送的数据包是不是被网络延迟了
    • 可以知道网络中是不是把发送端的数据包给复制了
  • 小结:
    • 如果数据包丢失或者ACK包丢失,超过一定时间会触发超时重传,超时时间RTO略大于RTT时间(发送数据到接收ACK包的时间间隔)
    • 为了解决超时等待的时间,提高效率,就有了快速重传,当有一个包丢失的时候,可以通过判断重复的ack进行快速重传,通过在TCP头部的选项字段里面添加SACK,就可以知道哪些包是丢失的,从而只重传丢失的包
    • 如果在ACK包丢失,导致的超时重传,发送端接收到接收端SACK从而知道收到了重复数据,这个SACK就是D-SACK,如果一个包由于网络问题导致的快速重传,也可以通过D-SACK来进行判断

2、TCP滑动窗口

TCP每次发送数据都要进行确认应答,当上一个包收到应答了再发下一个

  • 如果是一问一答的形式,则数据包往返的时间周期越长,通信效率就越低
  • 为了解决上面的问题,就有窗口概念,
    • 可以指定窗口大小,窗口大小是不需要等待确认应答,可以继续发送数据的最大值
    • 窗口是内核里面开辟的缓存区,需要保留发送的数据,只有收到应答才会从缓冲区中删除
    • TCP头部可以指定窗口大小,发送端会根据ACK返回的窗口大小,来发送数据,从而保证对端可以正常接收数据,所以窗口大小是由接收端决定的
  • 发送端的窗口
    • 有两个绝对指针:一个指向没有收到ack的第一个字节的序列号, 一个指向窗口中可用空间的第一个字节的序列号
    • 会根据ACK报文中的窗口大小进行调整,因为应用层不一定及时收数据
    • 此外,如果发送端窗口满了,没有及时收到ACK,就不能在应用层进行发送数据,如果序列号较前的收到ack,窗口会向右移动,存在可发空间,应用层可以继续拷贝发送数据
  • 接收端的窗口:可以接收发送端发送的数据量,一次能处理的数据量
    • 只有一个绝对指针,指向期望对端发送来的下一个字节的序列号
    • 窗口里面是还没进行确认的数据,也就是还没收到的数据,但是可以接收的数据大小
  • 发送端窗口约等于接收端窗口,因为传输存在延迟,不一定及时调整窗口大小,所以是约等于
  • 小结:
    • 三次握手确定窗口大小,接收端能接收多少数据,发送端根据接收端数据进行调整,去发送数据,在发送端窗口大小内,发送端可以一直发,并等待接收端返回ack确认号来发送窗口移动,每次ack报文都会携带窗口大小,可能会改变;

3、TCP流量控制

利用滑动窗口实现流量控制,发送端不能一股脑的发过去,如果对方处理不过来就会触发重传机制

  • 流量控制:发送方 根据 接收方的实际接收能力发送数据,也就是接收端滑动窗口的大小
  • TCP内核缓冲区和滑动窗口的关系:缓冲区大小会影响窗口大小
    • 应用层不及时收取数据,会导致窗口变小:
      • TCP滑动窗口(指针实现)是处于TCP缓冲区中间的,如果接收端接收到数据并返回ACK,但是应用层没有及时收取,当缓冲区内存不够,可能会导致滑动窗口变小,当窗口大小变成0,就发生了窗口关闭
    • 系统资源减少,会导致缓冲区变小:
      • 如果用户空间没有及时读取缓冲区数据,并且接收缓冲区由于系统资源突然变小,发送端来不及调整,会导致数据丢包现象,这是因为先减少缓冲区再收缩窗口
      • 所以不允许同时减少缓冲又收缩窗口,而先收缩窗口后一段时间再减少缓冲,从而避免丢包
  • 窗口关闭
    • 窗口大小为0的情况,就会阻止发送端发送数据,直到大小变成非0
    • 如果接收端窗口变成非0,会通过发送携带窗口大小的ACK报文,如果ACK报文丢失,发送端会一直等待,造成死锁问题
    • 如何避免死锁问题:当窗口关闭,就会启动一个持续计时器,如果超时就会发送一个窗口探测报文,接收端收到这个报文,就会返回一个携带当前窗口大小的ACK报文,如果窗口依旧为0,就会重启持续计时器
  • 糊涂窗口综合症
    • 接收端太忙,会导致发送端的窗口越来越小,到最后只有接收端腾出字节空间,发送端就会马上发送,但是TCP/IP包头就有40字节,有数据就传输的话,开销太大了
    • 导致的原因是:
      • 接收端告知小窗口大小
      • 发送端发送小数据
    • 如何避免:
      • 接收方不告知小窗口,窗口小于某个值就发送窗口为0的ACK,阻止对端发送数据
      • 发送发避免发送小数据,开启Nagle算法,避免小包发送
  • Nagle算法思想,延时处理,满足下面一个条件即可:
    • 窗口大小>=MSS并且数据大小>=MSS
    • 收到前一个数据的ack报文
  • 一般需要搭配 不通知小窗口给发送方+开启Nagle算法才能避免糊涂窗口综合症

4、TCP拥塞控制

  • 流量控制:是为了避免,发送端 数据填满 接收端的缓存,但是流量控制并不知道网络中发送的情况

  • 网络拥塞:网络发生拥堵的时候,继续发送大量数据包,就可能导致数据包延时、丢失等情况,TCP就会重传数据,一旦重传就会导致网络更加拥堵,从而不断恶性循环

  • 拥塞控制避免发送方的数据填满整个网络,并且为了调节发送数据的量,定义了一个拥塞窗口(cwnd)的概念

  • 拥塞窗口(cwnd):是发送方维护的一个状态变量,会根据网络的拥塞程度进行变化,滑动的发送窗口=min(滑动的接收窗口,拥塞窗口),当网络没有出现拥塞,cwnd窗口就会越大,当网络出现拥塞,cwnd就会越小

  • 如何判断网络拥塞:发送方没有在指定时间接收到ACK应答报文,也就是发送超时重传,就会认为网络出现拥塞了

  • 拥塞控制主要是四算法:

    • 慢启动:(指数增长)
      • TCP建立连接后,一点点点提高数据包发送的数量,发送端没收到一个ACK,拥塞窗口cwnd的大小就会+1;
      • 存在一个慢启动门限ssthresh,如果cwnd<ssthresh使用的就是慢启动算法,如果cwnd>=ssthresh,就使用拥塞避免算法;ssthresh一般大小为65535字节
    • 拥塞避免
      • 没收到一个ACK,cwnd增加1/cwnd,是为了确保cwnd的线性增长
      • 如果一直保持增长,网络就会慢慢进入拥塞状态,从而出现了丢包现象
      • 如果触发了重传机制,就会进入拥塞发生算法
    • 拥塞发送
      • 发生重传(超时、快速)的时候就会进入拥塞发生算法
      • 超时重传的拥塞发生:
        • ssthresh会设置为cwnd/2,并且cwnd会回复为初始值,linux的初始值是10(10个MSS);
        • 设置完ssthreshcwnd之后,会重新开始慢启动;
        • 这种方式下来的拥塞发生太激进了,容易造成网络卡顿
      • 快速重传的拥塞发生:
        • 设置cwndcwnd/2,再设置ssthreshcwnd
        • 设置完之后,会进入快速回复算法
    • 快速回复
      • 当发生快速重传的时候,表示网络不是太糟糕,一般快速回复和快速重传同时使用
      • 进入快速回复前, cwndssthresh都全部设置完了
      • 快速回复
        • cwnd = ssthresh+3,3表示接收到了三个数据包
        • 重传丢失的数据包;
        • 如果再收到重复的ACKcwnd就+1
        • 如果收到的是新的ACK,表示网络没问题了,则将cwnd设置为ssthresh,进入拥塞避免状态;
  • 拥塞控制算法过程:

    • 从TCP三次握手建立连接开始,发送端开始慢启动,没收到一个包的ACK,拥塞窗口就会+1,如果达到阈值,就会进入拥塞避免算法,每收到一个包的ACK,拥塞窗口就会增加窗口的倒数,从而保证拥塞窗口的线性增加
    • 当遇到丢包的情况,就判断为网络拥塞,从而重复重传机制,进入拥塞发送算法,根据重传机制的不同,拥塞发送算法也会不同
    • 超时重传,sthresh=cwnd/2,并且cwnd=初始值,重新重慢启动开始
    • 快速重传,cwnd=cwnd/2,ssthresh=cwnd,开启快速回复
    • 快速回复:先是设置cwnd=ssthresh+3,并重传丢失数据包,如果依旧重复收到相同的ACK,就会重复触发快速重传和快速回复,如果收到的是新的数据包,则进入拥塞避免状态。

参考文章:小林coding

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

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

相关文章

第十三课:QtCmd 命令行终端应用程序开发

功能描述&#xff1a;开发一个类似于 Windows 命令行提示符或 Linux 命令行终端的应用程序 一、最终演示效果 QtCmd 不是因为它是 Qt 的组件&#xff0c;而是采用 Qt 开发了一个类似 Windows 命令提示符或者 Linux 命令行终端的应用程序&#xff0c;故取名为 QtCmd。 上述演示…

FreeMarker系列--list的用法(长度,遍历,下标,嵌套,排序)

原文网址&#xff1a;FreeMarker系列--list的用法&#xff08;长度,遍历,下标,嵌套,排序&#xff09;_IT利刃出鞘的博客-CSDN博客 简介 本文介绍FreeMarker的list的用法。 大小 Java ArrayList<String> list new ArrayList<String>(); Freemaker ${list?s…

W5500-EVB-PICO 做UDP Server进行数据回环测试(七)

前言 前面我们用W5500-EVB-PICO 开发板在TCP Client和TCP Server模式下&#xff0c;分别进行数据回环测试&#xff0c;本章我们将用开发板在UDP Server模式下进行数据回环测试。 UDP是什么&#xff1f;什么是UDP Server&#xff1f;能干什么&#xff1f; UDP (User Dataqram P…

图数据库_Neo4j学习cypher语言_使用CQL命令002_删除节点_删除属性_结果排序Order By---Neo4j图数据库工作笔记0006

然后我们再来看如何删除节点 可以看到首先 我们这里 比如我要删除张三 可以看到 match (n:student) where n.name = "张三" delete n 这样就是删除了student集合中,name是张三的节点 然后我们再来看 如何来删除关系 match (n:student)-[r]->(m:student) where…

机器学习、cv、nlp的一些前置知识

为节省篇幅&#xff0c;不标注文章来源和文章的问题场景。大部分是我的通俗理解。 文章目录 向量关于向量的偏导数&#xff1a;雅可比矩阵二阶导数矩阵&#xff1a;海森矩阵随机变量随机场伽马函数beta分布数学术语坐标上升法协方差训练集&#xff0c;验证集&#xff0c;测试集…

Nginx的安装及负载均衡搭建

一.Nginx的安装 1&#xff09;准备安装环境 yum install -y make gcc gcc-c pcre-devel pcre zlib zlib-devel openssl openssl-develPERE PCRE(Perl Compatible Regular Expressions)是一个Perl库&#xff0c;包括 perl 兼容的正则表达式库。 nginx的http模块使用pcre来解…

前端jd要求:了解一门后端开发语言优先 解决方案之Node.js

前端jd要求&#xff1a;了解一门后端开发语言优先 解决方案之Node.js 前言常见的后端开发语言一、什么是 Node.js二、学习 Node.js 的前置知识三、学习 Node.js 的步骤1、Node.js 的安装2、Node.js 的基本语法和 API模块导入和导出文件读写操作HTTP 服务器命令行参数 3、Node.j…

可能导致不可接受的信息安全事件发生的核电站事故。

立陶宛伊格纳利纳核电站&#xff08;1992 年&#xff09; 一名在该核电站工作的程序员将恶意代码上传到一个负责反应堆子系统运行的自动化系统中&#xff0c;该系统被及时发现。 但如果没有及时发现&#xff0c;谁知道会发生什么呢&#xff1f;核电站被关闭以进行调查。有关这…

Vue-8.集成(.editorconfig、.eslintrc.js、.prettierrc)

介绍 同时使用 .editorconfig、.prettierrc 和 .eslintrc.js 是很常见的做法&#xff0c;因为它们可以在不同层面上帮助确保代码的格式一致性和质量。这种组合可以在开发过程中提供全面的代码维护和质量保证。然而&#xff0c;这也可能增加一些复杂性&#xff0c;需要谨慎配置…

Coreutils工具包,Windows下使用Linux命令

之前总结过两篇有关【如何在Windows系统下使用Linux的常用命令】的文章&#xff1a; GnuWin32&#xff0c;Windows下使用Linux命令 UnxUtils工具包&#xff0c;Windows下使用Linux命令 今天再推荐一个类似的工具包Coreutils 一、简介 GNU core utilities是GNU操作系统基本…

【HDFS】hdfs的count命令的参数详解

Usage: hadoop fs -count [-q] [-h] [-v] [-x] [-t [<storage type>]] [-u] [-e] [-s] <paths

(学习笔记-进程管理)怎么避免死锁?

死锁的概念 在多线程编程中&#xff0c;我们为了防止多线程竞争共享资源而导致数据错乱&#xff0c;都会在操作共享资源之前加上互斥锁&#xff0c;只有成功获得到锁的线程&#xff0c;才能操作共享资源&#xff0c;获取不到锁的线程就只能等待&#xff0c;直到锁被释放。 那…

创建一个简单的HTML Viewer应用程序

使用wxPython和内嵌浏览器来创建一个简单的HTML Viewer应用程序。 在本篇文章中&#xff0c;我们将使用Python和wxPython模块来创建一个简单的HTML Viewer应用程序。这个应用程序可以让用户输入HTML内容&#xff0c;并在内嵌浏览器中显示该内容的效果。 准备工作 在开始之前…

apache doris和StarRocks的区别

记录一下最新要用到2个新数据库的区别 Apache Doris是一个分布式的列式存储系统&#xff0c;它的设计目标是提供大规模数据处理的可靠性和高性能。Doris采用了集群方式&#xff0c;通过将数据分布在多个机器上进行处理来提高性能&#xff0c;并提供了SQL查询接口方便用户使用。…

QT:定时器事件

定时器第一种办法&#xff1a; 1.利用事件timerEvent&#xff0c;在帮助文档中找到该字段&#xff1a;[override virtual protected] void QTimer::timerEvent(QTimerEvent *e) 重写该虚函数 //重写定时器事件void timerEvent(QTimerEvent *e);2.启动定时器startTimer(1000); …

区间预测 | MATLAB实现QRGRU门控循环单元分位数回归时间序列区间预测

区间预测 | MATLAB实现QRGRU门控循环单元分位数回归时间序列区间预测 目录 区间预测 | MATLAB实现QRGRU门控循环单元分位数回归时间序列区间预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 MATLAB实现QRGRU门控循环单元分位数回归时间序列区间预测。基于分位…

卷积神经网络教程 (CNN) – 使用 TensorFlow 在 Python 中开发图像分类器

在这篇博客中,让我们讨论什么是卷积神经网络 (CNN) 以及 卷积神经网络背后的架构——旨在解决 图像识别系统和分类问题。 卷积神经网络在图像和视频识别、推荐系统和自然语言处理方面有着广泛的应用。 目录 计算机如何读取图像? 为什么不是全连接网络?

[GitOps]微服务版本控制:使用ArgoCD 部署Grafana Loki

背景介绍 请回答&#xff1a;你们是如何保证线上部署的服务&#xff0c;从服务版本到参数配置&#xff0c;都是和测试通过的版本是一致的呢&#xff1f; 本文将介绍GitOps的基本原理以及ArgoCD的使用&#xff1a;ArgoCD部署Grafana Loki 到k8s集群。 本文项目地址&#xff1…

详细介绍如何使用 OpenCV 对图像进行锐化

将了解锐化图像的过程,我们将使用内核来突出显示每个特定像素并增强其发出的颜色。它与模糊过程非常相似,只不过现在我们不是创建一个内核来平均每个像素强度,而是创建一个内核,该内核将使像素强度更高,因此对人眼来说更加突出。 了解流程的后端。 很高兴知道内核用于模糊…

Nginx 解决api跨域问题

环境: nginx 1.22.1 宝塔8.0 php lavarel 在nginx里加入下面的设置 #这里填*就是任何域名都允许跨域add_header Access-Control-Allow-Origin "*";#CORS请求默认不发送Cookie和HTTP认证信息。但是如果要把Cookie发到服务器&#xff0c;要服务器同意&#xff0c…