前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >TCP速度慢?注意WS窗口因子~

TCP速度慢?注意WS窗口因子~

原创
作者头像
陈佳
修改于 2019-06-30 13:10:11
修改于 2019-06-30 13:10:11
9.7K0
举报
文章被收录于专栏:佳爷的专栏佳爷的专栏

【写在前面的话】

本文介绍一下Window Scaling的概念,以及配套的例子运用。转载请标明出处~~


【目录】

1、窗口因子介绍

2、案例介绍


什么是WS(window scaling)?

tpc有两个窗口,一个是滑动窗口,一个是拥塞窗口。WS与滑动窗口相关。通过增加一个因子来扩大默认滑动窗口的值。

滑动窗口的定义:收到ACK之前可以连续发送的字节数。举个例子,某接收端的窗口值假设为10240字节,假设发送端发的包每次都是1024字节大小,那么发送端可以连续发送10个包,而不需要收到接收端的ACK确认。

窗口大小占TCP头部16位,也就是窗口值最大能有:2^16=65535bytes=64K

65535字节到底有多大?在以前网速没有那么快的情况下是足够使用的,但是随着网速的不断提升,65535字节不够用了。

有个比喻叫填满水管(填网络链路)。自己按照理解画了张图。满打满算,水管的最大限度就是下图的矩形面积

有个计算方法: bandwidth * delay。带宽乘以延迟。

假设有两台主机连接在10Mbps的网络上,单程耗时是80ms。统一换算成字节。水管的面积就是:10,000,000bps/8bit*0.08秒=100,000bytes/s,也就是发送端可以连续发送100,000字节的数据给接收端。问题是刚才说了TCP的窗口大小最大只有65,535字节。也就是发送端尽全力发,最多也只有65,535字节可以发。

水管绿色部分就被浪费掉了。因此引入了WS,在tcp的option中增加16位作为滑动窗口因子window scaling。窗口值*窗口因子=最终的窗口值。但是并不是所有的客户端、服务端都支持窗口因子的。

为了更直观的看窗口因子,拿了两台服务器抓包。

【场景一】两端都支持窗口因子

窗口因子是在TCP三次握手时,SYN包进行同步的。

如上图,TCP第一个包:

10.123.4.10告诉10.123.4.4自己的窗口大小是29200,窗口因子是128。因此总大小是29200*128=3,737,600bytes这个值就远远大过默认的65,535bytes。

最底下的tcp option说明了窗口因子是7,2^7=128。这个128是算好了的,而且告诉你直接multiple 128。

TCP第二个包:

10.123.4.4告诉10.123.4.10,自己的窗口是28960,窗口因子是128。

【场景二】只有一端支持窗口因子

接下来我把10.123.4.4的窗口因子支持功能关闭。抓包如下:

还是一样,第一个包,10.123.4.10告知10.123.4.4自己的窗口大小是29200,同时窗口因子是128

第二个包,10.123.4.4告诉10.123.4.10,自己的窗口大小是28960,并没有什么窗口因子

第三个包,10.123.4.10也没有继续使用窗口因子了,最后红框可以看出(no window scaling used)

总结一下:

1、两端都支持,窗口因子才会最终被启用。如有一端不支持,则因子不会被使用。

2、窗口因子是在TCP的SYN包协商的,而且只协商一次。也就是滑动窗口是根据实际情况进行变化的,但是因子是固定的。


【一个案例】

用户访问源站速度正常,用户通过代理访问源站则速度慢

原因就在窗口因子上,代理和客户端本身支持窗口因子,但源站没有开启窗口因子协商。

在客户端直接访问源站的情况下,TCP三次握手情况如下,

客户端得知源站不支持窗口因子,于是接下来数据包的发送,滑动窗口的值就直接了当了。该给多少给多少。举个例子,原本客户端告知源站自己的窗口是1024,因子是1,总数就是1024*2^1=2048

但是从源站发回来的包得知源站并不支持因子,于是,接下来的包客户端在告知源站的时候,直截了当,窗口是2048。

客户端通过代理再去访问源站的情况如下:

客户端和代理都支持窗口因子,因此在step1的协商中,使用了窗口因子。且step1是优先于step2的。毕竟代理是先和客户端建联,然后在和源站建联。

但是在step2中,源站是不支持因子的,代理和源站之间协商的结果,没有使用窗口因子。

举个例子:

step1中,客户端告知代理,自己的win是1024,因子是1,总量就是1024*2^1=2048

step2中,代理告知源站一样的情况,win是1024,因子是1。但是源站不支持因子,于是就变成了,总量是1024。

于是,情况就变成了,前面的水管大,后面的水管小。整条链路上看,水管变小了。

【解决办法】

源站打开窗口因子的支持功能。

vim /etc/sysctl.conf

添加

net.ipv4.tcp_window_scaling = 1 #写入配置文件,永久生效

sysctl -p #立刻生效

sysctl -a | grep tcp_window #查看生效结果

参考资料:https://packetlife.net/blog/2010/aug/4/tcp-windows-and-window-scaling/

【后记】

江湖人称佳爷~~专注于解决公有云各类问题,喜欢讨论,欢迎来撩~~

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
c语言学习之数组3
#include <stdio.h> int main() {   char cArr[] = {'I', 'L', 'O', 'V', 'E', 'C'};   char sArr[] = "ilovec";   int i = sizeof(cArr);   int j = sizeof(sArr);   printf("字符数组的长度:%d, 字符串的长度: %d", i, j);     return 0; }
py3study
2020/01/14
4210
C语言之字符、整数、数组、字符串笔记
每种类型占用内存空间不一样,比如char占一个字节,short占2个字节,int占4个字节,double占8个字节
tandaxia
2018/09/27
2.8K0
C语言之字符、整数、数组、字符串笔记
c语言基础学习05_数组和字符串
============================================================================= 涉及到的知识点有:for循环有两种写法、数组、一维数组定义与使用、一维数组的初始化、 如何得到一个一维数组的成员数量、查找出一维数组中成员最大值、查找一维数组的第二大元素的值、 一维数组的逆置、一维数组排序:冒泡排序、二维数组、二维数组的初始化、三维数组初始化、三维数组排序、 字符串与字符数组、字符数组的初始化、字符数组的使用(以及字符数组和字符串的区别)、去除输出字符串结尾处的空格、 现在要去掉字符串最右面的空格,而不能去掉字符串中间的空格呢、随机数产生函数rand与srand、 自动的变种子、控制随机数的范围、用scanf来输入字符串、如何把两次输入的字符串放到新的字符串里去、 scanf缓冲区溢出的危险的解释、字符串的逆置。 ============================================================================= for循环有两种写法:
黑泽君
2018/10/11
2.5K0
C/C++ 学习笔记七(内存管理)
相对于其他语言,C、C++的一大利器便是可以非常灵活的控制内存。与此同时,另一方面灵活的带来的要求也是十分严格,否则会出现令人头疼的分配错误、内存越界、内存泄漏等众多内存问题。 程序内存结构 C程序的
Celebi
2017/08/25
2K0
C/C++ 学习笔记七(内存管理)
一文带你了解c++和c中字符串的使用
对于c语言当中,你好像没有看到有关于字符串定义的关键字,不像我们常规的整型、浮点型、字符类型、指针、数组、结构体等数据类型,都能够一眼就能看出他们是什么数据类型,但是如果你对c语言理解不是很深的话,那你可能就不能"享受"到这里面的"美味"用法了,既然标题都标注了这个,我也不卖关子,下面会有总结分享的。说完了c,那么对于我们的c++来说,它定义字符串就简单多了,因为有关键字来定义,你一看就知道。那么下面大家就随着我的笔步一起来看看究竟吧!
用户6280468
2022/03/21
8040
一文带你了解c++和c中字符串的使用
redis学习 - sds字符串
Redis 设计与实现:如果想要知道redis底层,这本书可以给予不少的帮助,非常推荐每一位学习redis的同学去翻一翻。
阿东
2021/08/16
3280
redis学习 - sds字符串
C语言——I/深入理解指针(五)
sizeof是操作符,计算变量所占内存内存空间大小的,单位是字节,如果操作数是类型的话,计算的是使⽤类型创建的变量所占内存空间的大小。 sizeof 只关注占⽤内存空间的大小,不在乎内存中存放什么数据。
用户11015888
2024/03/11
810
初识C语言·指针(5)
sizeof是C语言的关键字,被用来计算某个数据在内存中占的空间大小,不会关心存放的是什么数据。sizeof有个值得注意的点就是sizeof后面是类型的话一定加括号,如果是变量的话可以不用加,其次就是sizeof的返回值是size_t类型的,打印的时候需要用%zd打印,最后的结果单位是字节。
_lazy
2024/10/16
560
初识C语言·指针(5)
[C语言]初阶指针和结构体
内存:内部存储器,暂存程序/数据——掉电丢失 SRAM,DRAM,DDR,DDR2,DDR3。
IT编程爱好者
2023/04/12
5380
[C语言]初阶指针和结构体
C/C++ 学习笔记三(函数)
导语 函数在编程语言中可谓“头等公民”,理解函数的实现原理,函数的一些方法论对于编程非常有好处。 我将从函数的实现原理以及编写函数的一些建议两个的角度来重新认识一下C、C++中的函数。 那具体函数在汇
Celebi
2017/08/21
1.2K0
C/C++ 学习笔记三(函数)
C语言字符串详解
字符串是一种非常重要的数据类型,但是C语言不存在显式的字符串类型,C语言中的字符串都以字符串常量的形式出现或存储在字符数组中。同时,C 语言提供了一系列库函数来对操作字符串,这些库函数都包含在头文件 string.h 中。
小林C语言
2020/12/25
3.9K0
C语言字符串详解
聊点基础的--sizeof,strlen,数组,字符串在一起能整哪些坑?
对于初学者来说,sizeof,strlen,数组,字符串整在一起是痛苦的,它总能在某些莫名其妙的时候整一个措手不及。本文看看它们在一起能挖什么坑。
编程珠玑
2019/11/24
1K0
redis为什么不直接使用C字符串,而要自定义简单动态字符串?
Redis (一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。)没有直接使用 C 语言传统的字符串表示redis中的字符串,而是使用了一种名为简单动态字符串(simple dynamic string,SDS)的抽象类型, 并将 SDS 用作 Redis 的默认字符串。
编程珠玑
2020/05/22
1.5K0
C++学习笔记---------基础知识sizeof用法
返回值的类型是标准库命名为size_t的类型,size_t类型定义在cstddef头文件中,该头文件是C标准库的头文件stddef.h的C++版本。他是一个和 机器相关的unsigned类型,其大22:14:53小足以保证内存中对象的大小。
ccf19881030
2019/04/29
5830
【C】数组和指针练习
这里的printf("%d\n", strlen(*arr)); printf("%d\n", strlen(arr[1]))在运行时会报错,所以下面的运行结果不包括这两个,具体原因见后文
阿伟@t
2023/10/10
2050
【C】数组和指针练习
【C 语言】字符串操作 ( strlen 与 sizeof 函数 | 计算 字符串长度 与 内存块大小 )
strlen() 函数的作用是获取字符串大小 , 其原理是 从 内存某个首地址 开始计数 , 知道碰到 '\0' 字符结束 , 计算字符串长度 , 其中 计数中 不包含 '\0' 字符 ;
韩曙亮
2023/03/29
1.3K0
【C 语言】字符串操作 ( strlen 与 sizeof 函数 | 计算 字符串长度 与 内存块大小 )
【重拾C语言】六、批量数据组织(三)数组初值;字符串、字符数组、字符串数组;类型定义 typedef
本文介绍了C语言:数组初值;字符串、字符数组、字符串数组;类型定义 typedef
Qomolangma
2024/07/30
1220
【重拾C语言】六、批量数据组织(三)数组初值;字符串、字符数组、字符串数组;类型定义 typedef
C语言进阶——字符串&&内存函数
  这是牛客网上的一道简单题:判断输入字符是否为字母,一般的解决方法是通过ASCII码判断,不过这样做的话判断表达式较长,此时我们可以利用C语言中的库函数isalpha(判断是否为字母) 来完成这个题目,不仅代码量少,而且通俗易懂。要实现这种效果,就需要学习C语言中的各种库函数,而本文会列出大多数字符串函数和内存函数的使用及其实现,如果你想学习C语言库函数或对字符串、内存有好奇之心,不妨仔细来看看吧!🎉🎉🎉
北 海
2023/07/01
5220
C语言进阶——字符串&&内存函数
C语言0长度数组(可变数组/柔性数组)详解
众所周知, GNU/GCC 在标准的 C/C++ 基础上做了有实用性的扩展, 零长度数组(Arrays of Length Zero) 就是其中一个知名的扩展.
用户6280468
2022/06/09
6.2K0
C语言0长度数组(可变数组/柔性数组)详解
Apple 操作系统可执行文件 Mach-O
Mach-O 的全称是 Mach Object File Format。可以是可执行文件,目标代码或共享库,动态库。Mach 内核的操作系统比如 macOS,iPadOS 和 iOS 都是用的 Mach-O。Mach-O 包含程序的核心逻辑,以及入口点主要功能。
用户7451029
2020/06/16
3K0
推荐阅读
相关推荐
c语言学习之数组3
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档