林沛满--快递员的工作策略——TCP窗口

news2025/7/19 4:20:58

本文整理自:《Wireshark网络分析就这么简单 第1版》
作者:林沛满 著
出版时间:2014-12

假如你是一位勤劳的快递员,要送100个包裹到某公司去,怎样送货才科学?

最简单的方式是每次送1个,总共跑100趟。当然这也是最慢的方式,因为往返次数越多,消耗的时间就越长。除了需要减肥的快递员,一般人不会选择这种方式。最快的方式应该是一口气送100个,这样只要跑一趟就够了。可惜现实没有这么美好,往往存在各种制约因素:公司狭小的前台只容得下20个包裹,要等签收完了才能接着送;更令人郁闷的是,电瓶车只能装10个包裹。综合这两个因素,不难推出电瓶车的运力是效率瓶颈,而前台的空间则不构成影响。

快递送货的策略非常浅显,几乎人人可以理解,而TCP传输大块数据的策略却很少人懂。事实上这两者的原理是相似的。

TCP显然不用电瓶车送包,但它也有“往返”的需要。因为发包之后并不知道对方能否收到,要一直等到确认包到达,这样就花费了一个往返时间。假如每发一个包就停下来等确认,一个往返时间里就只能传一个包,这样的传输效率太低了。最快的方式应该是一口气把所有包发出去,然后一起确认。但现实中也存在一些限制:接收方的缓存(接收窗口)可能一下子接受不了这么多数据;网络的带宽也不一定足够大,一口气发太多会导致丢包事故。所以,发送方要知道接收方的接收窗口和网络这两个限制因素中哪一个更严格,然后在其限制范围内尽可能多发包。这个一口气能发送的数据量就是传说中的TCP发送窗口。

发送窗口对性能的影响有多大?一图胜千言,图1显示了发送窗口为1个MSS(即每个TCP包所能携带的最大数据量)和2个MSS时的差别。在相同的往返时间里,右边比左边多发了两倍的数据量。而在真实环境中,发送窗口常常可以达到数十个MSS。

在这里插入图片描述

图2就是在真实环境中抓的包,抓包时服务器10.32.106.73正往客户端10.32.106.103发数据。由于服务器的发送窗口很大,所以收到读请求之后,它在没有客户端确认的情况下连续发了10个包。

在这里插入图片描述

接着我把客户端的接收窗口强制成2920,相当于两个TCP包能携带的数据量。从图3中可以看到客户端通过“win=2920”把自己的接收窗口告诉服务器。因此服务器把发送窗口限制为2920,每发两个包就停下来等待客户端的确认。同样一个14215字节的读操作,图2只用1个往返时间就完成了,而图3则用了6个。

在这里插入图片描述

为了更好地说明这个过程,我把27号包到32号包用对话的形式表示出来,括号内的文字为我添加的注释。

27号包:客户端:“当前我的接收窗口是2920。”
28号包:服务器:“(好,那我的发送窗口就定为2920。)先给你1460字节。”
29号包:服务器:“再给你1460字节。(哎呀!我的发送窗口2920用完了,不能再发了。)”
30号包:客户端:“你发过来的2920字节已经处理完毕,所以现在我的接收窗口又恢复到2920。”
31号包:服务器:“(好,那我再把发送窗口定为2920。)给你一个1460字节。”
32号包:服务器:“再给你1460字节。(哎呀!我的发送窗口2920又用完了,不能再发了。)”

你也许有个疑问,本文的开头不是说有两个限制因素吗?这个例子只提到了接收窗口对发送窗口的限制,那网络的影响呢?由于网络的影响方式非常复杂,所以本文暂时跳过。下一篇文章将作详细介绍。

不知道出于何种原因,TCP发送窗口的概念被广泛误解,比如,很多人会把接收窗口误认为发送窗口。我经常想在论坛上回答相关提问,却不知道该从何答起,因为有些提问本身就基于错误的概念。下面是一些经常出现的问题。

1.如图4的底部所示,每个包的TCP层都含有“window size:”(也就是win=)的信息。这个值表示发送窗口的大小吗?

在这里插入图片描述

这不是发送窗口,而是在向对方声明自己的接收窗口。在此例子中,10.32.106.103向10.32.106.73声明自己的接收窗口是64093字节。10.32.106.73收到之后,就会把自己的发送窗口限制在64093字节之内。很多教科书上提到的滑动窗口机制,说的就是这两个窗口的关系,本文就不再赘述了。

假如接收方处理数据的速度跟不上接收数据的速度,缓存就会被占满,从而导致接收窗口为0。如图5的Wireshark截屏所示,89.0.0.85持续向89.0.0.210声明自己的接收窗口是win=0,所以89.0.0.210的发送窗口就被限制为0,意味着那段时间发不出数据。

在这里插入图片描述

2.我如何在包里看出发送窗口的大小呢?

很遗憾,没有简单的方法,有时候甚至完全没有办法。因为,当发送窗口是由接收窗口决定的时候,我们还可以通过“windowsize:”的值来判断。而当它由网络因素决定的时候,事情就会变得非常复杂(下篇文章将会详细介绍)。大多数时候,我们甚至不确定哪个因素在起作用,只能大概推理。以图5为例,接收方声明它的接收窗口等于0,那接收窗口肯定起了限制作用(因为不可能再小了),因此可以大胆地判断发送窗口就是0。再回顾本文开头10.32.106.73向10.32.106.103传数据的两个例子。第一个例子中,我们只能推理出10.32.106.73的发送窗口不小于那10个包(39~48号)携带的数据总和,但具体能达到多少却不得而知,因为窗口还没用完时读操作就完成了。第二个例子比较容易分析,因为传了两个包就停下来等确认,所以发送窗口是那两个包携带的数据量2920。

3.发送窗口和MSS有什么关系?

发送窗口决定了一口气能发多少字节,而MSS决定了这些字节要分多少个包发完。举个例子,在发送窗口为16000字节的情况下,如果MSS是1000字节,那就需要发送16000/1000=16个包;而如果MSS等于8000,那要发送的包数就是16000/8000=2了。

4.发送方在一个窗口里发出n个包,是不是就能收到n个确认包?

不一定,确认包一般会少一些。由于TCP可以累积起来确认,所以当收到多个包的时候,只需要确认最后一个就可以了。比如本文中10.32.106.73向10.32.106.103传数据的第一个例子中,客户端用一个包(包号49)确认了它收到的10个包(39~48号包)。

5.经常听说“TCP Window Scale”这个概念,它究竟和接收窗口有何关系?

在TCP刚被发明的时候,全世界的网络带宽都很小,所以最大接收窗口被定义成65535字节。随着硬件的革命性进步,65535字节已经成为性能瓶颈了,怎么样才能扩展呢?TCP头中只给接收窗口值留了16bit,肯定是无法突破65535 (2^16 - 1)的。

1992年的RFC 1323中提出了一个解决方案,就是在三次握手时,把自己的Window Scale信息告知对方。由于Window Scale放在TCP头之外的Options中,所以不需要修改TCP头的设计。Window Scale的作用是向对方声明一个Shift count,我们把它作为2的指数,再乘以TCP头中定义的接收窗口,就得到真正的TCP接收窗口了。

以图6为例,从底部可以看到10.32.106.159告诉10.32.106.103说它的Shift count是5。25等于32,这就意味着以后10.32.106.159声明的接收窗口要乘以32 才是真正的接收窗口值。

在这里插入图片描述

接下来我们再看图7中的3号包。10.32.106.159声明它的接收窗口为“Window size value:183”,183乘以32得到5856,所以Wireshark就显示出“Win=5856”了。要注意Wireshark是根据Shiftcount计算出这个结果的,如果抓包时没有抓到三次握手,Wireshark就不知道该如何计算,所以我们有时候会很莫名地看到一些极小的接收窗口值。还有些时候是防火墙识别不了WindowScale,因此对方无法获得Shiftcount,最终导致严重的性能问题。

在这里插入图片描述

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

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

相关文章

uCOSIII实时操作系统 八 软件定时器

目录 软件定时器概述 使用步骤: 创建软件定时器: 启动软件定时器: 停止软件定时器: 删除软件定时器: 单次定时器: ​编辑周期定时器: 无初始化延时: 有初始化延时&#xff…

LabVIEW中使用Get LV Class Default Value 出现错误1498

LabVIEW中使用Get LV Class Default Value 出现错误1498 在LabVIEW中开发了一个应用程序,其中包含可以在执行时动态配置插件的基类。生成可执行文件后,当应用程序要执行子类时,收到以下错误信息。 Error1498 occurred at Gen LV Class Defa…

Sandboxie+Buster Sandbox Analyzer打造个人沙箱

一、运行环境和需要安装的软件 实验环境:win7_x32或win7_x64 用到的软件:WinPcap_4_1_3.exe、Sandboxie-3-70.exe、Buster Sandbox Analyzer 重点是Sandboxie必须是3.70版本。下载地址:https://github.com/sandboxie-plus/sandboxie-old/blo…

Linux性能优化--使用性能工具发现问题

9.0 概述 本章主要介绍综合运用之前提出的性能工具来缩小性能问题产生原因的范围。阅读本章后,你将能够: 启动行为异常的系统,使用Linux性能工具追踪行为异常的内核函数或应用程序。启动行为异常的应用程序,使用Linux性能工具追…

浪子带你【25天】玩转Python——期中福利

人生苦短,我用Python! 目录 回顾上文 正文 最后的话 回顾上文 浪子带你【25天】玩转Python——5.面向对象编程(类和对象)-CSDN博客 正文 哈喽,不知不觉中,浪子的【25天】玩转Python已经开播13天啦&#xff01…

【c++智能指针】

目录 一、智能指针的使用及原理二、auto_ptr三、unique_ptr三、shared_ptr四、weak_ptr五、定制删除器 一、智能指针的使用及原理 RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网…

新型的终端复用器 tmux

以前遇到长时间执行任务时,一般是使用nohup加后台运行,但是涉及到少量代码编写。 同事介绍了一个screen命令,根据文档,此命令已经过时,最新的命令是tmux。 tmux的介绍文档,RedHat的这一篇非常不错。 在文…

vue ref和$refs获取dom元素

vue ref和$refs获取dom元素 **创建 工程: H:\java_work\java_springboot\vue_study ctrl按住不放 右键 悬着 powershell H:\java_work\java_springboot\js_study\Vue2_3入门到实战-配套资料\01-随堂代码素材\day04\准备代码\14-ref和$refs获取dom对象 vue --ve…

Kotlin中的数值类型

在Kotlin中,Byte、Short、Int、Long、Float和Double是基本数据类型,用于表示不同范围和精度的数值。 Byte(字节):Byte类型是8位有符号整数类型,取值范围为-128到127。在Kotlin中,可以使用字面值…

《深入浅出OCR》第三章:OCR文字检测

✨专栏介绍: 经过几个月的精心筹备,本作者推出全新系列《深入浅出OCR》专栏,对标最全OCR教程,具体章节如导图所示,将分别从OCR技术发展、方向、概念、算法、论文、数据集等各种角度展开详细介绍。 👨‍💻面向对象: 本篇前言知识主要介绍深度学习知识,全面总结知知识…

Linux Zabbix企业级监控平台+cpolar实现远程访问

文章目录 前言1. Linux 局域网访问Zabbix2. Linux 安装cpolar3. 配置Zabbix公网访问地址4. 公网远程访问Zabbix5. 固定Zabbix公网地址 前言 Zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案。能监视各种网络参数,保证服务器系…

C++stack和queue模拟实现以及deque的介绍

stack和queue介绍以及模拟实现 1.stack1.1stack的介绍1.2stack的使用 2.queue2.1queue的介绍2.2queue的使用 3.容器适配器3.1什么是适配器 4.stack模拟实现5.queue的模拟实现6.deque(双端队列) 1.stack 1.1stack的介绍 stack的文档介绍 stack是一种容…

软信天成:流程管理是企业精细化管理的一大利器

流程管理(BPM)是指组织和管理内部或跨部门的工作流程,主要包括设计、建模、执行、监控和优化业务流程,确保工作按照标准化的步骤进行,从而提高效率、降低成本,促进业务增长。 一、流程管理生命周期五大步骤…

xml文件报错 ORA-00907: 缺失右括号

原来的sql 更改之后 加一个select * from ()

VScode platformio的使用

一、platformio 工程创建 打开vscode界面你会发现左下多了个家的小图标,点击这里就可以进入platformio。 在右侧Quick Access栏中,有4个选项。可以看得出来,我们这里直接点击创建一个新的工程。 点击New Project打开project配置界面&#x…

Android---自定义View

当 Android SDK 中提供的系统 UI 控件无法满足业务需求时,需要考虑自己实现 UI 控件。掌握自定义控件,是理解整套 Android 渲染体系的基础。自定义 UI 控件有2种方式: 继承系统提供的成熟控件(比如 LinearLayout、RelativeLayout、…

美国跨境金融科技公司【Zolve】完成1亿美元融资

来源:猛兽财经 作者:猛兽财经 猛兽财经获悉,总部位于美国纽约的跨境金融科技公司Zolve近期宣布已经完成1亿美元融资。 本轮融资由CIM投资 该公司打算将这笔资金用于在英国、加拿大和澳大利亚的进一步扩张。 Zolve由创始人Raghunandan G领导&…

自由程序员想接私活?那你还不得知道这几个接单平台!最后一个就是宝藏!!

相信喜欢搞钱的程序员都知道,平常在平台上接点私活,利用闲暇时间接单是搞钱的常用套路,可是你确定你选对平台了吗?不管你是刚准备接单的小白,还是已经干了一段时间的老油条,都建议你看完本期文章&#xff0…

Spring框架(三)

1、代理模式: 二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标…

【译】快速开始 Compose 跨平台项目

原文: Compose Multiplatform application 作者:JetBrains 注意 Compose Multiplatform 中的 iOS 部分目前处于 Alpha 状态。以后可能会有不兼容的更改,届时也许需要手动进行迁移。 你可以使用这个模板来开发同时支持桌面、安卓和 iOS 的跨平…