TCP详解之流量控制
TCP详解之流量控制
发送方不能无脑的发数据给接收方,要考虑接收方处理能力。
如果一直无脑的发数据给对方,但对方处理不过来,那么就会导致触发重发机制,从而导致网络流量的无端的浪费。
为了解决这种现象发生,TCP 提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是所谓的流量控制。
下面举个栗子,为了简单起见,假设以下场景:
- 客户端是接收方,服务端是发送方
- 假设接收窗口和发送窗口相同,都为
200
- 假设两个设备在整个传输过程中都保持相同的窗口大小,不受外界影响
根据上图的流量控制,说明下每个过程:
- 客户端向服务端发送请求数据报文。这里要说明下,本次例子是把服务端作为发送方,所以没有画出服务端的接收窗口。
- 服务端收到请求报文后,发送确认报文和 80 字节的数据,于是可用窗口
Usable
减少为 120 字节,同时SND.NXT
指针也向右偏移 80 字节后,指向 321,这意味着下次发送数据的时候,序列号是 321 - 客户端收到 80 字节数据后,于是接收窗口往右移动 80 字节,
RCV.NXT
也就指向 321,这意味着客户端期望的下一个报文的序列号是 321,接着发送确认报文给服务端。 - 服务端再次发送了 120 字节数据,于是可用窗口耗尽为 0,服务端无法再继续发送数据。
- 客户端收到 120 字节的数据后,于是接收窗口往右移动 120 字节,
RCV.NXT
也就指向 441,接着发送确认报文给服务端。 - 服务端收到对 80 字节数据的确认报文后,
SND.UNA
指针往右偏移后指向 321,于是可用窗口Usable
增大到 80。 - 服务端收到对 120 字节数据的确认报文后,
SND.UNA
指针往右偏移后指向 441,于是可用窗口Usable
增大到 200。 - 服务端可以继续发送了,于是发送了 160 字节的数据后,
SND.NXT
指向 601,于是可用窗口Usable
减少到 40。 - 客户端收到 160 字节后,接收窗口往右移动了 160 字节,
RCV.NXT
也就是指向了 601,接着发送确认报文给服务端。 - 服务端收到对 160 字节数据的确认报文后,发送窗口往右移动了 160 字节,于是
SND.UNA
指针偏移了 160 后指向 601,可用窗口Usable
也就增大至了 200。
操作系统缓冲区与滑动窗口的关系
前面的流量控制例子,我们假定了发送窗口和接收窗口是不变的,但是实际上,发送窗口和接收窗口中所存放的字节数,都是放在操作系统内存缓冲区中的,而操作系统的缓冲区,会被操作系统调整。
当应用进程没办法及时读取缓冲区的内容时,也会对我们的缓冲区造成影响。
那操作系统的缓冲区,是如何影响发送窗口和接收窗口的呢?
我们先来看看第一个例子。
当应用程序没有及时读取缓存时,发送窗口和接收窗口的变化。
考虑以下场景:
- 客户端作为发送方,服务端作为接收方,发送窗口和接收窗口初始大小为
360
; - 服务端非常的繁忙,当收到客户端的数据时,应用层不能及时读取数据。
根据上图的流量控制,说明下每个过程:
- 客户端发送 140 字节数据后,可用窗口变为 220 (360 - 140)。
- 服务端收到 140 字节数据,但是服务端非常繁忙,应用进程只读取了 40 个字节,还有 100 字节占用着缓冲区,于是接收窗口收缩到了 260 (360 - 100),最后发送确认信息时,将窗口大小通告给客户端。
- 客户端收到确认和窗口通告报文后,发送窗口减少为 260。
- 客户端发送 180 字节数据,此时可用窗口减少到 80。
- 服务端收到 180 字节数据,但是应用程序没有读取任何数据,这 180 字节直接就留在了缓冲区,于是接收窗口收缩到了 80 (260 - 180),并在发送确认信息时,通过窗口大小给客户端。
- 客户端收到确认和窗口通告报文后,发送窗口减少为 80。
- 客户端发送 80 字节数据后,可用窗口耗尽。
- 服务端收到 80 字节数据,但是应用程序依然没有读取任何数据,这 80 字节留在了缓冲区,于是接收窗口收缩到了 0,并在发送确认信息时,通过窗口大小给客户端。
- 客户端收到确认和窗口通告报文后,发送窗口减少为 0。
可见最后窗口都收缩为 0 了,也就是发生了窗口关闭。当发送方可用窗口变为 0 时,发送方实际上会定时发送窗口探测报文,以便知道接收方的窗口是否发生了改变,这个内容后面会说,这里先简单提一下。
我们先来看看第二个例子。
当服务端系统资源非常紧张的时候,操作系统可能会直接减少了接收缓冲区大小,这时应用程序又无法及时读取缓存数据,那么这时候就有严重的事情发生了,会出现数据包丢失的现象。
说明下每个过程:
- 客户端发送 140 字节的数据,于是可用窗口减少到了 220。
- 服务端因为现在非常的繁忙,操作系统于是就把接收缓存减少了 120 字节,当收到 140 字节数据后,又因为应用程序没有读取任何数据,所以 140 字节留在了缓冲区中,于是接收窗口大小从 360 收缩成了 100,最后发送确认信息时,通告窗口大小给对方。
- 此时客户端因为还没有收到服务端的通告窗口报文,所以不知道此时接收窗口收缩成了 100,客户端只会看自己的可用窗口还有 220,所以客户端就发送了 180 字节数据,于是可用窗口减少到 40。
- 服务端收到了 180 字节数据时,发现数据大小超过了接收窗口的大小,于是就把数据包丢失了。
- 客户端收到第 2 步时,服务端发送的确认报文和通告窗口报文,尝试减少发送窗口到 100,把窗口的右端向左收缩了 80,此时可用窗口的大小就会出现诡异的负值。
所以,如果发生了先减少缓存,再收缩窗口,就会出现丢包的现象。
为了防止这种情况发生,TCP 规定是不允许同时减少缓存又收缩窗口的,而是采用先收缩窗口,过段时间再减少缓存,这样就可以避免了丢包情况。
窗口关闭
在前面我们都看到了,TCP 通过让接收方指明希望从发送方接收的数据大小(窗口大小)来进行流量控制。
如果窗口大小为 0 时,就会阻止发送方给接收方传递数据,直到窗口变为非 0 为止,这就是窗口关闭。
窗口关闭潜在的危险
接收方向发送方通告窗口大小时,是通过 ACK
报文来通告的。
那么,当发生窗口关闭时,接收方处理完数据后,会向发送方通告一个窗口非 0 的 ACK 报文,如果这个通告窗口的 ACK 报文在网络中丢失了,那麻烦就大了。
这会导致发送方一直等待接收方的非 0 窗口通知,接收方也一直等待发送方的数据,如不采取措施,这种相互等待的过程,会造成了死锁的现象。
TCP 是如何解决窗口关闭时,潜在的死锁现象呢?
为了解决这个问题,TCP 为每个连接设有一个持续定时器,只要 TCP 连接一方收到对方的零窗口通知,就启动持续计时器。
如果持续计时器超时,就会发送窗口探测 ( Window probe ) 报文,而对方在确认这个探测报文时,给出自己现在的接收窗口大小。
- 如果接收窗口仍然为 0,那么收到这个报文的一方就会重新启动持续计时器;
- 如果接收窗口不是 0,那么死锁的局面就可以被打破了。
窗口探测的次数一般为 3 次,每次大约 30-60 秒(不同的实现可能会不一样)。如果 3 次过后接收窗口还是 0 的话,有的 TCP 实现就会发 RST
报文来中断连接。
糊涂窗口综合症
如果接收方太忙了,来不及取走接收窗口里的数据,那么就会导致发送方的发送窗口越来越小。
到最后,如果接收方腾出几个字节并告诉发送方现在有几个字节的窗口,而发送方会义无反顾地发送这几个字节,这就是糊涂窗口综合症。
要知道,我们的 TCP + IP
头有 40
个字节,为了传输那几个字节的数据,要搭上这么大的开销,这太不经济了。
就好像一个可以承载 50 人的大巴车,每次来了一两个人,就直接发车。除非家里有矿的大巴司机,才敢这样玩,不然迟早破产。要解决这个问题也不难,大巴司机等乘客数量超过了 25 个,才认定可以发车。
现举个糊涂窗口综合症的栗子,考虑以下场景:
接收方的窗口大小是 360 字节,但接收方由于某些原因陷入困境,假设接收方的应用层读取的能力如下:
- 接收方每接收 3 个字节,应用程序就只能从缓冲区中读取 1 个字节的数据;
- 在下一个发送方的 TCP 段到达之前,应用程序还从缓冲区中读取了 40 个额外的字节;
每个过程的窗口大小的变化,在图中都描述的很清楚了,可以发现窗口不断减少了,并且发送的数据都是比较小的了。
所以,糊涂窗口综合症的现象是可以发生在发送方和接收方:
- 接收方可以通告一个小的窗口
- 而发送方可以发送小数据
于是,要解决糊涂窗口综合症,就要同时解决上面两个问题就可以了:
- 让接收方不通告小窗口给发送方
- 让发送方避免发送小数据
怎么让接收方不通告小窗口呢?
接收方通常的策略如下:
当「窗口大小」小于 min( MSS,缓存空间/2 ) ,也就是小于 MSS 与 1/2 缓存大小中的最小值时,就会向发送方通告窗口为 0
,也就阻止了发送方再发数据过来。
等到接收方处理了一些数据后,窗口大小 >= MSS,或者接收方缓存空间有一半可以使用,就可以把窗口打开让发送方发送数据过来。
怎么让发送方避免发送小数据呢?
发送方通常的策略如下:
使用 Nagle 算法,该算法的思路是延时处理,只有满足下面两个条件中的任意一个条件,才可以发送数据:
- 条件一:要等到窗口大小 >=
MSS
并且 数据大小 >=MSS
; - 条件二:收到之前发送数据的
ack
回包;
只要上面两个条件都不满足,发送方一直在囤积数据,直到满足上面的发送条件。
Nagle 伪代码如下:
if 有数据要发送 {if 可用窗口大小 >= MSS and 可发送的数据 >= MSS {立刻发送MSS大小的数据} else {if 有未确认的数据 {将数据放入缓存等待接收ACK} else {立刻发送数据}}
}
注意,如果接收方不能满足「不通告小窗口给发送方」,那么即使开了 Nagle 算法,也无法避免糊涂窗口综合症,因为如果对端 ACK 回复很快的话(达到 Nagle 算法的条件二),Nagle 算法就不会拼接太多的数据包,这种情况下依然会有小数据包的传输,网络总体的利用率依然很低。
所以,接收方得满足「不通告小窗口给发送方」+ 发送方开启 Nagle 算法,才能避免糊涂窗口综合症。
另外,Nagle 算法默认是打开的,如果对于一些需要小数据包交互的场景的程序,比如,telnet 或 ssh 这样的交互性比较强的程序,则需要关闭 Nagle 算法。
可以在 Socket 设置 TCP_NODELAY
选项来关闭这个算法(关闭 Nagle 算法没有全局参数,需要根据每个应用自己的特点来关闭)
setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&value, sizeof(int));
相关文章:
TCP详解之流量控制
TCP详解之流量控制 发送方不能无脑的发数据给接收方,要考虑接收方处理能力。 如果一直无脑的发数据给对方,但对方处理不过来,那么就会导致触发重发机制,从而导致网络流量的无端的浪费。 为了解决这种现象发生,TCP 提…...
mac根目录下创建文件不能问题
mac根目录下创建文件不能问题 解决办法2: 原因 mac os引入了系统完整性保护(SIP)机制,无法在/、/usr目录下新建文件 解决办法1: 打开终端,输入 csrutil status显示enabled表示启用了SIP,接下来需要禁用SIP…...
stable diffusion model训练遇到的问题【No module named ‘triton‘】
一天早晨过来,发现昨天还能跑的diffusion代码,突然出现了【No module named ‘triton’】的问题,导致本就不富裕的显存和优化速度雪上加霜,因此好好探究了解决方案。 首先是原因,由于早晨过来发现【电脑重启】导致了【…...
线性dp,优化记录,273. 分级
273. 分级 273. 分级 - AcWing题库 给定长度为 N 的序列 A,构造一个长度为 N 的序列 B,满足: B 非严格单调,即 B1≤B2≤…≤BN 或 B1≥B2≥…≥BN。最小化 S∑Ni1|Ai−Bi|。 只需要求出这个最小值 S。 输入格式 第一行包含一…...
JWT 安全及案例实战
文章目录 一、JWT (json web token)安全1. Cookie(放在浏览器)2. Session(放在服务器)3. Token4. JWT (json web token)4.1 头部4.1.1 alg4.1.2 typ 4.2 payload4.3 签名4.4 通信流程 5. 防御措施 二、漏洞实例(webgoa…...
Vue2+Vue3
文章目录 Vue快速上手Vue是什么第一个Vue程序插值表达式Vue核心特性:响应式 Vue指令v-htmlv-show 与 v-ifv-else 与 v-else-ifv-onv-bindv-forv-model指令修饰符 计算属性watch侦听器(监视器)watch——简写watch——完整写法 Vue生命周期 和 …...
华为云云耀云服务器L实例评测|redis漏洞回顾 MySQL数据安全解决 搭建主从集群MySQL 相关设置
前言 最近华为云云耀云服务器L实例上新,也搞了一台来玩,期间遇到过MySQL数据库被攻击的情况,数据丢失,还好我有几份备份,没有造成太大的损失;后来有发现Redis数据库被攻击的情况,加入了redis密…...
【C++】详解std::thread
2023年9月10日,周日下午开始 2023年9月10日,周日晚上23:35完成 虽然这篇博客我今天花了很多时间去写,但是我对std::thread有了一个完整的认识 不过有些内容还没完善,以后有空再更新.... 目录 头文件类的成员类型方法(construc…...
Apache HTTPD 漏洞复现
文章目录 Apache HTTPD 漏洞复现1. Apache HTTPD 多后缀解析漏洞1.1 漏洞描述1.2 漏洞复现1.3 漏洞利用1.4 获取GetShell1.5 漏洞防御 2. Apache HTTPD 换行解析漏洞-CVE-2017-157152.1 漏洞描述2.2 漏洞复现2.3 漏洞利用2.4 修复建议 3. Apache HTTP Server_2.4.49 路径遍历和…...
【C++从入门到精通】第2篇:C++基础知识(中)
文章目录 2.1 iostream介绍:cout、cin和endl2.1.1 输入/输出库2.1.2 std::cout2.1.3 std::endl2.1.4 std::cout是缓冲的2.1.5 std::endl与\n2.1.6 std::cin2.1.7 总结2.1.8 练习时间 2.2 未初始化的变量和未定义的行为2.2.1 未初始化的变量2.2.2 未定义行为2.2.3 明…...
【RuoYi移动端】uni-app中实现生成二维码功能(代码示例)
完整示例: <template><view><view class"titleBar">执法检查“通行码”信息</view><view class"twoCode"><canvas canvas-id"qrcode"></canvas></view></view> </templat…...
深度解剖数据在栈中的应用
> 作者简介:დ旧言~,目前大一,现在学习Java,c,c,Python等 > 座右铭:松树千年终是朽,槿花一日自为荣。 > 望小伙伴们点赞👍收藏✨加关注哟💕…...
Android10 SystemUI系列 需求定制(一)状态栏控制中心默认tile定制属性适配
一、前言 SystemUI 所包含的界面和模块比较多,这一节主要分享一下控制中心默认tile 列表的实现,通过配置可以实现 下拉状态栏,控制中心默认的tile显示 二、准备工作 按照惯例先找一下控制中心的代码,主要在下面这个路径下 frameworks/base/packages/SystemUI/src/com/andr…...
【微信小程序】文章设置
设置基本字体样式:行高、首行缩进 font-size: 32rpx;line-height: 1.6em;text-indent: 2em;padding: 20rpx 0;border-bottom: 1px dashed var(--themColor); 两端对齐 text-align: justify; css文字两行或者几行显示省略号 css文字两行或者几行显示省略号_css…...
程序员在线周刊(冒泡算法篇)
大家好,欢迎来到程序员在线周刊!本期我们将深入探讨一种经典的排序算法——冒泡算法,并附上具体的代码实现。 目录 简介代码原理广告广告1广告2广告3 简介 冒泡算法是一种简单但效率较低的排序算法,它的原理非常直观:…...
string
目录 六、STL简介 (一)什么是STL (二)STL的版本 (三)STL六大组件 七、string (一)标准库中的string 1、string类 2、string常用的接口 1)string类对象的常见构造 2)string类对象的容量操作 3)string类对象的访问及遍历操作 4)string类对象的修改操作 5)string类非成…...
html的日期选择插件
1.效果 2.文档 https://layui.gitee.io/v2/docs/ 3.引入 官网地址: https://layui.gitee.io/v2/ 引入(在官网下载,)jquery-1.7.2.min.js,layui/layui.js **<link href"js/layui/css/layui.css" rel"stylesh…...
OPPO哲库事件 “ 始末 ” ! 集体打哑谜?
1►OPPO哲库解散 2019 年,美国商务部以“科技网络安全”为由,将华为公司及其70家附属公司列入出口管制“实体名单”。与此同时,OPPO 创始人兼 CEO陈明永对外宣布,公司将为未来三年内投入 500 亿元用于前沿技术和深水区技术的探索…...
数据聚类分析
K均值 1.1 数据来源(随机生成) import matplotlib.pyplot as plt from sklearn.datasets import make_blobsX, y make_blobs(n_samples150,n_features2,centers3,cluster_std0.5,shuffleTrue,random_state0) # plt.scatter(X[:, 0], X[:, 1], cwhite, markero, edgecolorsbl…...
前 40 个 Microsoft Excel 面试问题答案
1)什么是 Microsoft Excel? Microsoft Excel 是一个电子电子表格应用程序,使用户可以使用按行和列细分的电子表格系统,使用公式存储,组织,计算和处理数据。 它还提供了使用外部数据库进行分析,…...
ros2学习笔记:shell环境变量脚本setup.bash[-z][-n][-f]参数作用
-n作用 [ -n 字符串 ] or [ 字符串 ] 字符串的长度为非零(有内容)则为真。加-n与不加-n结果相同。 -z作用 [ -z 字符串 ] 字符串的长度为零则为真。 字符串为空即NULL时为真,与上面的-n相反。 -f作用 [ -f FILE ] 如果 FILE 存在且是一…...
xss渗透(跨站脚本攻击)
一、什么是XSS? XSS全称是Cross Site Scripting即跨站脚本,当目标网站目标用户浏览器渲染HTML文档的过程中,出现了不被预期的脚本指令并执行时,XSS就发生了。 这里我们主要注意四点: 1、目标网站目标用户; 2、浏览…...
9参数化重采样时频变换,基于MATLAB平台,程序已调通,可直接替换数据进行分析。
参数化重采样时频变换,基于MATLAB平台,程序已调通,可直接替换数据进行分析。 9matlab参数化重采样时频变换 (xiaohongshu.com)...
RK3568平台开发系列讲解(调试篇)系统运行相关频率设置
🚀返回专栏总目录 文章目录 一、CPU 频率设置二、DDR 频率设置三、NPU 频率设置沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 CPU 默认是 interactive 状态,它会根据 CPU 使用率和目标负载来动态地调整 CPU 频率。为获得更高运行速度或者性能评估,我们需要手动固…...
嵌入式:驱动开发 Day2
作业:字符设备驱动,完成三盏LED灯的控制 驱动代码: mychrdev.c #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/io.h> #include &q…...
RK3399平台开发系列讲解(入门篇)VIM的基础命令
🚀返回专栏总目录 文章目录 一、Vim 命令速查二、其他命令三、Vim模式沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 本篇将介绍Vim相关命令。 一、Vim 命令速查 简单说明一下,这张图上展示了一个键盘。图中的“•”表示,单个字母不是完整的命令,必须再有进一步…...
Rocky Linux 安装图解(替代centos)服务器+桌面
centos自从20年底转变为不稳定版本后,有很多替代方案 经过近3年的发展,rocky linux算是一个比较好的选择,一是依照red hat企业版来做,二是rocky的发起者也是centos的创始人 如果想安装debian,可以参考:deb…...
webpack 基础配置
常见配置 文件打包的出口和入口webpack如何开启一台服务webpack 如何打包图片,静态资源等。webpack 配置 loader配置 plugin配置sourceMap配置 babel 语法降级等 接下来 , 我们先从webpack的基本配置 开始吧! 在准备 配置之前 , 搭建一个 …...
C语言和mfc按格式读取文件数据
fscanf()函数的功能是从文件中按格式读取一个或多个数据; 例如文件中有一行数据, 22 3.34 hello 则使用 fscanf(fp, "%d%f%s", &a, &f, str) 可一次读取整型、浮点、字符串三个数据; 此函数位于C标准库头文件<stdio…...
SQLyog 各版本下载与安装(目前最新版本为13.2.0)
文章目录 一、SQLyog Ultimate 各版本下载1. For Windows x642. For Windows x86 二、SQLyog Community 各版本下载1. For Windows x642. For Windows x863. For Linux x86_644. For Linux i386 三 、SQLyog 安装四、如何解决SQLyog试用期到期问题五、最后 数据库可视化工具&am…...
网站建设能在家工作室/制作网站用什么软件
使用JSON,在SERVLET或者STRUTS的ACTION中取得数据时 如果会出现异常:Java.lang.NoClassDefFoundError: net/sf/ezmorph/Morpher 原因是少了JAR包,造成类找不到 还必须有其它几个依赖包: commons-logging-1.0.4.jar commons-lang-2…...
百度 wordpress/营销型网站设计制作
文章目录一、 ELK日志分析系统概述1、ELK简介2、使用ELK的原因3、完整日志系统基本特征4、ELK的工作原理二、ELK日志分析系统集群部署的操作步骤1、 ELK Elasticsearch 集群部署(在Node1、Node2节点上操作)2、实例操作: ELK Elasticsearch 集…...
制作网站支付方式/营销策略有哪些内容
现在国内的 Java 主力版本仍是 Java 8,所以对于「Java 8 是否要收费」这个问题,十分有必要阐述清楚,以消除不必要的恐慌。首先要明确一点,Java 仍然是免费的,并不需要付费使用!下面解释「Java 8 要收费」这…...
律所网站建设国队男子接力赛/电商培训班一般多少钱一个月
一、问答题 1、自动化代码中,用到了哪些设计模式? 2、什么是Selenium 3、TestNG中注解有哪些? 4、什么是断言? 5、TestNG有哪些有点? 6、什么是web自动化测试? 7、写出Selenium中你最熟悉的接口或类…...
防伪码网站怎么做/百度网站大全
声明:本文是《 Java 7 Concurrency Cookbook 》的第六章,作者: Javier Fernndez Gonzlez 译者:许巧辉 校对:方腾飞 在本章中,我们将包含: 使用非阻塞线程安全的列表使用阻塞线程安全的列表用…...
国有林场网站建设/seo整站优化外包
质数概念质数 ,又称 素数 ,指在一个大于1的 自然数 中,除了1和此整数自身外,无法被其他自然数 整除 的数(也可定义为只有 1 和本身两个 因数 的数)。最小的素数是2,也是素数中唯一的偶数;其他素数都是奇数。…...