TCP详解(二)滑动窗口/流量控制

news2024/11/25 6:34:27

本文解释了TCP为何能保证数据传输的可靠性,以及如何保证整个网络的顺畅。

1 网络分层模型

这是一切的本质。网络被设计成分层的,所以网络的操作就可以称作一个“栈”,这就是网络协议栈的名称的由来。在具体的操作上,数据包最终形成的过程就是一层一层封装的过程,在栈上形成一段连续的数据,我们可以称作是一层一层的push操作。同样的,数据包的解封装的过程,则可以认为是一层一层的pop操作。

1.1 网络包的发送流程

  • 应用程序发送数据,调用send方法来将数据发送出去,此时便会触发系统调用来发送数据
  • 将用户数据从【用户空间】拷贝到【内核空间】,
  • 将数据封装为一个个【skb结构】(skb可以简单理解为一个封装待发送数据的数据结构,在内存层面待发送的数据都是以skb来表示并传递的。分配skb时会分配一个大小包含了所有协议头和数据长度的空结构,也就是最终发送出去的以太网帧的大小,随后经过不同协议层,不断的在skb中填充数据,为了防止不断扩充数组带来的消耗)
  • skb进入协议栈进行处理(分别经过传输层、网络层)
  • 然后skb会被传送到网卡【传输队列RingBuffer】里(网卡有多个队列,那么就有多个RingBuffer,并且每个队列对应一个发送队列一个接收队列),RingBuffer中存储的是skb的指针
  • 网卡将RingBuffer里面的数据真实的发送到网络上
  • 当网卡发送完数据后,网卡会向CPU发出一个数据发送完毕的【硬中断】
  • CPU响应该硬中断,找到硬中断处理函数,在硬中断处理函数里会发出软中断,然后由【内核线程ksoftirqd】去响应并处理软中断,【内核线程ksoftirqd】找到该软中断对应的处理函数(网卡驱动启动时注册的),然后进行调用,在处理函数中会清理RingBuffer
  • 等收到ack后会清理socket发送缓冲区

1.2 网络包的接收流程

网络包的接收流程主要涉及以下几个步骤:‌

  1. 网卡接收数据:‌当网络帧到达网卡时,‌网卡通过DMA(‌直接内存访问)‌方式将网络包放到收包队列中,‌并通过硬中断通知中断处理程序已经收到了网络包。‌
  2. 内核处理网络帧:‌网卡中断处理程序为网络帧分配内核数据结构(‌sk_buff)‌,‌并将其拷贝到sk_buff缓冲区中。‌然后通过软中断通知内核收到了新的网络帧。‌
  3. 协议栈处理:‌内核协议栈从缓冲区中取出网络帧,‌并通过网络协议栈从下到上逐层处理这个网络帧。‌例如,‌在链路层检查报文的合法性,‌找出上层协议的类型(‌IPv4还是IPv6)‌,‌去掉帧头、‌帧尾,‌然后交给网络层。‌
  4. 网络层处理:‌网络层取出IP头,‌判断网络包下一步的走向,‌如果是要发送到本机,‌则取出上层协议的类型(‌TCP或UDP)‌,‌去掉IP头,‌再交给传输层处理。‌
  5. 传输层处理:‌传输层取出TCP头或UDP头后,‌根据<源IP、‌源端口、‌目的IP、‌目的端口>四元组作为标识,‌找出对应的Socket,‌并把数据拷贝到Socket的接收缓存中。‌
  6. 应用程序读取数据:‌最后,‌应用程序可以使用Socket接口读取到新接收到的数据。‌

1.3 socket缓冲区

TCP的socket缓冲区是TCP协议为了实现可靠的数据传输而在内存中分配的临时存储区域,每个TCP socket连接都有两个缓冲区:发送缓冲区(send buffer)和接收缓冲区(receive buffer)。只要建立TCP连接,这两个缓冲区就会默认建立。

  • 发送缓冲区(Send Buffer): 发送缓冲区用于暂存应用程序打算通过TCP连接发送出去的数据。当应用程序调用send()或write()函数将数据写入socket时,数据并不会立即被发送到网络上,而是首先被放入发送缓冲区。TCP协议负责从缓冲区中取出数据,根据当前的网络状况和拥塞控制等因素逐步将数据发送到目标主机。如果发送缓冲区满,应用程序的写操作可能会被阻塞(在阻塞模式下)或者返回错误(在非阻塞模式下)。
  • 接收缓冲区(Receive Buffer): 接收缓冲区用于存储从网络中接收到但尚未被应用程序读取的数据。当数据包从网络到达时,TCP协议将它们放入接收缓冲区,等待应用程序通过recv()或read()函数读取。如果缓冲区满了而新的数据继续到达,超出部分的数据可能会被丢弃,或者根据TCP的流量控制机制暂时停止对方发送更多数据,以避免数据丢失。

2 滑动窗口

2.1 窗口详情

滑动窗口协议属于TCP协议的一种应用,用于网络数据传输时的流量控制,以避免拥塞的发生。该协议允许发送方在停止并等待确认前发送多个数据分组。由于发送方不必每发一个分组就停下来等待确认,因此该协议可以加速数据的传输,提高网络吞吐量。

TCP通过滑动窗口来进行流量控制。设想在发送端发送数据的速度很快而接收端接收速度却很慢的情况下,为了保证数据不丢失,显然需要进行流量控制, 协调好通信双方的工作节奏。所谓滑动窗口,可以理解成接收端所能提供的缓冲区大小。TCP利用一个滑动的窗口来告诉发送端对它所发送的数据能提供多大的缓冲区。由于窗口由16位bit所定义,所以接收端TCP 能最大提供65535个字节的缓冲。由此,可以利用窗口大小和第一个数据的序列号计算出最大可接收的数据序列号。

滑动窗口本质上是描述接受方的TCP数据报缓冲区大小的数据,发送方根据这个数据来计算自己最多能发送多长的数据。如果发送方收到接受方的窗口大小为0的TCP数据报,那么发送方将停止发送数据,等到接受方发送窗口大小不为0的数据报的到来。

TCP建立连接的初始,B会告诉A自己的接收窗口大小,比如为‘20’:字节31-50为发送窗口。

根据B给出窗口值,A构造自己的窗口

A发送11个字节后,发送窗口位置不变,B接收到了乱序的数据分组,因为最左侧31没收到,即使32、33收到了,给A返回的ack中的窗口依旧不变,也就是B只会返回收到的连续的字节数

只有当A成功发送了数据,即发送的数据得到了B的确认之后,才会移动滑动窗口离开已发送的数据;同时B则确认连续的数据分组,对于乱序的分组则先接收下来,避免网络重复传递,等31也收到后才会在ack中返回seq为34(下次接收的字节编号),同时窗口向右移动+3

如果34一直没收到,A会将剩余的窗口数据继续传过去,然后就不能在发送了

当B接收到所有数据后,假如应用程序一直未取数据,那就导致接收缓冲区中所有的数据都是待交付主机的状态,窗口也就是会变成0,ack就会为 seq=54,win=0

2.3 最大窗口限制

TCP的Window是一个16bit位字段,它代表的是窗口的字节容量,也就是TCP标准窗口最大为2^16 -1 = 65535个字节。

另外在TCP的选项字段中还包括了一个TCP窗口扩大因子,option-kind 为 3 ,option-length为 3 个字节(总字节数),option-data只占一个字节,取值范围 0 -14.窗口扩大因子用来扩大TCP窗口,可把原来16bit的窗口,扩大为31bit,这个在上一篇文章中解释过,详情请看 TCP详解(一)报文详情/MSS/MTU-CSDN博客

3 流量控制

所谓流量控制,主要是接收方传递信息给发送方,使其不要发送数据太快,是一种端到端的控制。主要的方式就是返回的ACK中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送

3.1 持续计时器

这里面涉及到一种情况,如果B已经告诉A自己的缓冲区已满,于是A停止发送数据;等待一段时间后,B的缓冲区出现了富余,于是给A发送报文告诉A我的rwnd大小为400,但是这个报文不幸丢失了,于是就出现A等待B的通知||B等待A发送数据的死锁状态。为了处理这种问题,TCP引入了持续计时器(Persistence timer),当A收到对方的零窗口通知时,就启用该计时器,时间到则发送一个1字节的探测报文,对方会在此时回应自身的接收窗口大小,如果结果仍未0,则重设持续计时器,继续等待。

TCP为每一个连接设有一个持续计时器。只有TCP的一方收到对方的零窗口通知,就启动持续计时器;只要持续计时器超时,就放送一个零窗口探测报文,携带一字节的数据;而对方收到零窗口探测报文时,回复自己现有的接收窗口值。如果窗口大小依旧是零,那么收到报文的一方就重新启动持续计时器。

持续计时器是为了解决双方相互等待(A等待B发送非零窗口的通知,B等待A发送数据)而形成的死锁现象。这种现象一般发生在发送窗口大小数据包丢失时。

3.2 RTT

RTT,全称Round Trip Time,即往返时间,数据发送时刻到接收到确认的时刻的差值。由链路传播时间、末端系统处理时间、路由器缓存中排队和处理的时间组成。

对于TCP来说,路由器缓存中排队和处理的时间会随着网络拥塞程度辩护而变化。通过计算RTT可以反应网络拥塞程度,从而拥塞控制。

3.3 RTO

RTO,全称Retransmission TimeOut,即重传超时时间即从数据发送时刻算起,超过这个时间便执行重传。。

超时之后TCP进入Loss状态,重传所有没有被确认的报文,同时进入慢启动的回复过程。

重传的时间RTO设定是非常重要的,如果设置太短,可能会导致并没有丢包而重传,如果设置太长了,可能因为等待ACK而浪费掉很多时间,牺牲传输的效率。从思想上来讲,其实我们还是希望重传的时间需要稍稍的大于RTT就可以了。但是这个RTT没有什么可以使用的定值,他是不断变化的,所以只能动态的进行设置,RTO只能是根据RTT来进行动态的设置

3.4 拥塞

随着网络上的主机不断增加其发送速率,会使整个网络变得非常拥挤;这会导致网络经常出现丢包现象,使网络传输效率大幅度下降。

如果不对网络做拥塞控制,会降低整个网络的传输效率

3.5 慢启动和拥塞控制

(1)一条TCP连接开始时,window size被设置为1 MSS(最大报文段大小)

(2)TCP发送方发送完发送窗口数据,并收到所有的确认,window size以指数增长(以2的倍数进行翻倍),即慢启动阶段。

(3)window size增长到一个慢启动的阈值thresh,开始执行拥塞控制算法(window size呈线性增长),进入拥塞控制阶段。

(4)随着window size增长,发送速率提高,出现网络拥塞,分组超时重传。比如丢包时,将慢启动门限设置为原来的一半,然后将cwnd设置为1,然后执行慢启动算法(起点较低,指数级增长)

上述方法的目的是在拥塞发生时循序减少 主机发送到网络中的分组数,使得发送拥塞的路由器有足够的时间去把队列中积压的分组处理完毕。

慢启动和拥塞控制算法常常作为一个整体使用,

3.6 快重传和快恢复

1990增加新的拥塞控制算法:快重传和快恢复。用于改进TCP的性能。

有时候,个别报文会在网络中丢失,当实际上网络并没有发生拥塞,这将导致发送方超时重传并认为网络出现了拥塞;从而错误的启动慢启动算法,因此降低传输效率。为此,引入快重传算法,可以让发送方尽早知道个别报文段的丢失。

所谓快重传,就是发送方尽快的进行重传,而不是等超时计时器超时才重传。快重传可以使整个网络吞吐量提高约20%。发送方接收到3个重复确认,就知道只丢失了个别报文段,于是不启动慢启动算法,而是执行快恢复算法。具体方式如下

  1. 当接受方建立这样的机制,如果一个包丢失,则对后续的包继续发送针对该包的重传请求
  2. 一旦发送方接收到三个一样的确认,就知道该包之后出现了错误,立刻重传该包;
  3. 此时发送方执行“快恢复”算法:①慢启动门限减半②CWND设为慢开始门限减半后的数值③执行拥塞避免算法(高起点,线性增长)

所谓快恢复,就是发送方将慢启动上限和拥塞窗口值调整为当前窗口的一半,开始执行拥塞避免算法。

快重传和快恢复是为了提高TCP传输的效率和可靠性

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

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

相关文章

tcpdump入门——抓取三次握手数据包

1. 使用docker启动一个tcp应用 参考&#xff1a;https://blog.csdn.net/LONG_Yi_1994/article/details/141175526 2. 获取容器id docker ps |grep gochat 3. 获取容器的 PID 首先&#xff0c;你需要获得容器的进程 ID&#xff08;PID&#xff09;。可以使用 docker inspect…

kafka下载|安装

1、下载kafka https://kafka.apache.org/downloads 2、安装kafka 解压下载的kafka安装包即可 tar -xvf kafka_2.13-3.7.0.tgz -C /usr/local/3、查看kafka目录 bin目录&#xff1a;存放了脚本 config目录&#xff1a;主要存放了配置文件

Pytest-BDD流程性接口测试和自定义测试报告

引言 上篇文章《Pytest-BDD实现接口自动化测试&#xff0c;并附全部代码》我们介绍了怎么使用Pytest-BDD实现接口自动化测试&#xff0c;本篇文章主要介绍怎么去做流程性接口测试和自定义测试报告相关内容。 流程性接口测试 流程性接口测试&#xff0c;指的是一个业务流需要…

【九芯电子】智能声控台灯语音模块,低成本语音识别芯片

在当今数字化时代&#xff0c;智能家居已经逐渐成为现代生活中的一部分。从温度调节到安全监控&#xff0c;我们对家居设备的控制已经更加便捷。然而&#xff0c;随着生活节奏的加快&#xff0c;用户对于更便捷的家庭控制方式的需求也在不断增加。针对这一关键的问题&#xff0…

HBO引爆血腥浪漫,尺度全开必看的影视剧推荐

一直以来我们的僵尸题材电影风靡全国&#xff0c;同时西方也创作出吸血鬼题材、丧尸题材的影视剧也是层出不穷&#xff0c;那今天我们就来探讨下吸血鬼题材的影视剧。 吸血鬼题材的影视剧&#xff0c;一直以来都是观众的宠儿。从光鲜亮丽的《暮光之城》到狗血多角恋的《吸血鬼日…

河北移动:核心系统数据库成功完成整体迁移 ,实现全栈国产|OceanBase案例

本文作者&#xff1a;移动通信集团河北有限公司架构规划专家&#xff0c;房瑞 项目背景&#xff1a; 中国移动通信集团河北有限公司一直在积极响应国家及集团的号召&#xff0c;以磐舟&磐基云原生为底座&#xff0c;结合国产浏览器、中间件、数据库、操作系统和服务器等&a…

树莓派4b无法选择声音输入输出设备问题

问题一&#xff1a;选择不了3.5mm音频输出口&#xff0c;也看不到音频输入设备 运行命令 &#xff1a;pactl load-module module-udev-detect tsched0 pactl load-module 命令用于在运行时加载新的模块。module-udev-detect 是PulseAudio的一个模块&#xff0c;它负责自动检测系…

【kubernetes】k8s对外服务之Ingress

一、Ingress介绍 1、Ingress的简介 K8S集群外部的客户端访问K8S集群内部的方案 基于Service实现&#xff1a;NodePort、LoadBalancer、externalIPs 只能支持四层代理转发&#xff0c;如果K8S集群规模较大运行的业务服务较多&#xff0c;NodePort端口/externalIPs管理成本…

Python套接字综合应用(UDP篇)

Python套接字综合应用(UDP篇) 1、 主要功能 UDP客户端实现UDP服务端实现输出字体颜色控制响应捕获键盘CtrlC信号套接字异常捕获及处理通信报文16进制格式化输出 2、 Python UDP套接字应用 Windows程序在WinServer2022上验证运行&#xff0c;Linux程序在银河麒麟V10上验证运…

[Java]面向对象-抽象类/方法接口适配器设计模式

抽象类 一个类中如果存在抽象方法&#xff0c;那么该类就必须申明为抽象类 定义格式&#xff1a; 如果一个类包含抽象方法&#xff0c;那么该类必须是抽象类。注意&#xff1a;抽象类不一定有抽象方法&#xff0c;但是有抽象方法的类必须定义成抽象类。 abstract class 类名…

haproxy七层代理详解之-完整安装部署流程及负载均衡实现-及热更新方法

一.负载均衡 1.1负载均衡时什么 负载均衡:Load Balance&#xff0c;简称LB&#xff0c;是一种服务或基于硬件设备等实现的高可用反向代理技术&#xff0c;负载均网络流量等)分担给指定的一个或多个后端特定的服务器或设备&#xff0c;从而提高了衡将特定的业务(web服务、公司…

嵌入式生物打印是什么?有啥优势?

大家好&#xff0c;今天我们来了解一下这篇《Embedded 3D bioprinting–An emerging strategy to fabricate biomimetic & large vascularized tissue constructs》发表于《Bioactive Materials》的一篇综述&#xff0c;在组织工程和再生医学领域&#xff0c;传统方法存在一…

【JUC】04-synchronized关键字

1. 悲观锁与乐观锁 悲观锁&#xff1a;认为自己在使用数据的时候一定会有别的线程来修改数据&#xff0c;因此在获取数据的时候会先加锁&#xff0c;确保数据不会被别的线程修改。synchroized和Lock的实现类都是乐观锁&#xff1a;认为自己在使用数据时不会有别的线程修改数据…

激光尘埃粒子计数器在洁净室监测中的关键应用(原理、类型、选型)

激光尘埃粒子计数器的应用 激光尘埃粒子计数器广泛应用于多个领域&#xff0c;包括但不限于&#xff1a; 权威机构&#xff1a;如血液中心、防疫站、疾控中心、质量监督所等。 生产企业和科研部门&#xff1a;如电子行业、制药车间、半导体、光学或精密机械加工、塑胶、喷漆…

构建流水线生产管理创新的RFID智能管理系统应用方案

在当今竞争激烈的制造业环境中&#xff0c;流水线生产的高效、精准和智能化管理已成为企业获取竞争优势的关键。然而&#xff0c;传统的流水线生产管理方式在应对日益复杂的生产需求和多变的市场环境时&#xff0c;逐渐暴露出诸多难点和痛点。 一、流水线生产管理的难点与痛点…

OCR调研

OCR调研 一、介绍 OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;是一种将图像中的文字转换为计算机可处理格式的技术。OCR技术经历了从传统OCR到基于深度学习的OCR的转变。深度学习OCR技术通过模拟人脑神经元结构处理文本和图像数据&am…

打造高效存储与访问体验:NFS共享携手Nginx负载均衡,赋能企业级数据流通与性能优化

作者简介&#xff1a;我是团团儿&#xff0c;是一名专注于云计算领域的专业创作者&#xff0c;感谢大家的关注 座右铭&#xff1a; 云端筑梦&#xff0c;数据为翼&#xff0c;探索无限可能&#xff0c;引领云计算新纪元 个人主页&#xff1a;团团-CSDN博客 目录: 前言&#…

AIGC实践|AI助力一张照片生成百变写真

前言&#xff1a; 在之前的文章中&#xff0c;我们已经领略了 AI 在动态有声绘本、小游戏开发、视频短片制作以及包装设计等领域的神奇应用&#xff0c;在本篇文章中&#xff0c;我将尝试利用AI辅助&#xff0c;使用一张照片生成个性化写真集。充分满足工作艺术照、各地郊游打…

关于自己部署AI大模型踩的坑(二)—— GPU篇

最近一直在研究如何打算属于我自己的J.A.R.V.I.S.&#xff08;钢铁侠中的机器人管家&#xff09;。 上一篇写了我最近在部署自己的大模型&#xff0c;使用llama3.1&#xff0c; 和通义千问2。虽然最终结果也是成功了&#xff0c;过程却十分地坎坷。 所以这一篇文章一是总结其中…

linux学习--第一天

--linux基础命令 -本地安装 1. sudo dpkg -i 软件包 &#xff1a;安装单个软件包 2. sudo dpkg -i * .deb &#xff1a;安装多个软件包 3. sudo dpkg -L 软件包&#xff1a;列出软件在系统中文件路径 4. sudo dpkg -s 软件包&#xff1a;列出软件包的安装状态 5. …