TCP/IP协议(五、tcp滑动窗口)_windows下默认的tcp窗口值是多少-程序员宅基地

技术标签: tcp  # TCP/IP协议  tcp滑动窗口  滑动窗口  

终于来到了TCP的滑动窗口,本来计算第二节就讲滑动窗口,但是每次都是计划赶不上变化,一推再推,所以来到了第5节,不过也不晚,趁早搞懂TCP/IP还是很有用的。

5.1 延时ACK

TCP的一个重点知识点延时ACK,但是还是从交互式通信讲起。

5.1.1 交互式通信

"交互式"TCP连接是指,该连接需要在客户端和服务器之间传输用户输入信息,如按键操作、短消息、操作杆或鼠标的动作等。这些包都是比较小的包,如果没一个很小的包都要组成一个报文来传输,那么传输协议需要耗费很高的代价,因为每个交换分组中包含的有效负载字节较少。反之,报文段较大怎会引入更大的延时。对延迟敏感类应用(如在线游戏,协同工具等)造成负面影响。因此需要找到一个折中的方法、

交互式通信其实比较简单,就是客户端获取用户输入信息,然后将其传给服务器。服务器对命令进行解析并生成相应返回给客户端。有点像一请求一应答模式。

但是让我也奇怪的是,每个交互按键通常都会生成一个单独的数据包。也就是说,每个按键都是独立传输的(每次一个字符而非每次一行,说实话,我不是看到TCP详解中说,我也很纳闷,这么会这样设计)。

像我们平时使用的ssh和服务器通信的话,服务器需要对输入字符做出回显。所以这个过程应该是这样子的:
在这里插入图片描述
如果将数据字节确认和数据字节回显合并的话,会不会高效一点,这种方法就是我们下面说的延时确认。

5.1.2 延时确认

在许多情况下,TCP并不对每个到来的数据包都返回ACK,利用TCP的累积ACK字段(这个我也不是很清楚,清楚的可以在下面留言)就能实现这个功能。累积确认可以允许TCP延迟一段时间发送ACK,以便将ACK和相同方向上需要传的数据结合发送。TCP实现ACK延时的时延应小于500ms。实践中时延最大取200ms.

采用延时ACK的方法会减少ACK传输的数目,可以一定程度地减轻网络负载。

用法:
通常TCP在某些情况下使用延时ACK的方法,但时延不会很长。
在大数据包传输中只要采用的是拥塞控制和延时ACK。
在小数据包传输中,如交互式应用,需要采用另外的算法。(就是下面说的Nagle算法)

5.1.3 Nagle算法

从前面的讲解可以看出,ssh连接中,通常单次击键就会引发数据流的传输,这些小包的数据量不到,但是需要带上整个TCP/ip头,所以会造成很高的网络传输代价。所以John提出了一种简单有效的解决方法,现在成其为Nagle算法。下面讲解一下这个算法的含义;

  • 当一个TCP连接中有在传数据(即那些已发送但还为经确认的数据),小的报文段(长度小于SMSS)就不能被发送,直到所有的再传数据都收到ACK
  • 在收到ACK之后,TCP需要收集这些小数据,讲起整合到一个报文段中发送。

举个栗子:
首先观察禁用Nagle算法的情况:
在这里插入图片描述
这一个图是从tcp/ip详解中截取出来的,我们先看下面,F1键我是输入了3个字符,在禁用Nagle算法的时候,是每一个字符单独发送,所以我们看到的是3个单独的包,在服务器回复ack的时候,出现了丢包,客户端没有接受到ack2,服务器会重传一个ack2.客户端就接收到后,就回复了ack6,说明6之前的包都接收好了,这个在滑动窗口有说过。

然后第二个按键也是3个字符,这样就不说了,都是一样的。

通过这个例子我们明显感觉到,小包太多了,这样很浪费网络资源,所以就提出了Nagle算法。

下面我们来看看开启了Nagle算法之后的效果:
在这里插入图片描述
这就是开启Nagle算法的过程,是不是中间没有小包的存在了,通信也简洁了。

但是这样子会带来一个问题:
有没有发现每次发送一个请求报文之后,回复的ACK都是200ms左右,这就是延时ACK决定的,服务器收到了一个请求报文,会开启一个定时器,等待200ms,如果这时候再次接受到客户端的请求,会两个ack做为一个返回,但是犹豫客户端使用的是Nagle算法,他会一直等待ACK才会再次发送请求,这里就会形成一个死锁,不过这个死锁不是一直的,直到延时ack超时之后,就会给客户端发送ack了,客户端就会可以再次发送了,这也是看到图发现一个请求都是等待200ms左右才有回应。

总结:
从前面的例子可以看出,在有些情况下并不适用Nagle算法。

典型的包括那些要求时延尽量小的应用,如远程控制中鼠标或按键操作需要及时送达以得到快键的反馈。
还有多人网络游戏,人物的动作需要及时地传送以确保不影响游戏进程。

禁用Nagle算法也简单,可以设置TCP_NODELAY选项即可。

5.2 滑动窗口

TCP是传输控制协议,socket:流式套接字,顺序。
我们应用层都是用socket来接收的,那我们接收的数据怎么保证顺序性呢?
我们要知道网络中传输各种情况都有可能发生,前一个包选择了一个路由路径,后一个包就可能选择另外的一个路由,可能会导致后面的包比前面的包提前到大。

所以我们接下来说的TCP协议栈中使用滑动窗口这种机制来确保接收数据的顺序性。

5.2.1 发送窗口

TCP连接的每一端斗可收发数据。连接的收发数据量是通过一组窗口结构来维护的。每个TCP活动连接的两端都维护一个发送窗口结构和接收窗口结构。

接下来先看看发送窗口的结构:
在这里插入图片描述
发送窗口有四个部分,第一个部分已发送并已经确认,就是接收端已经回复了ACK,第二个部分已经发送但未经确认,这一部分可能在传输中,也可能已经被接收了,但是由于没有到延时ack的时间,所以还没确认,第三部分即将发送,将要发送的数据,其中第二部分和第三部分是由接收端通告的窗口称为提供窗口,是接收到3字节之后,回复ack中,顺带了一个6字节大小的窗口,在之前TCP初识的这篇,有介绍过窗口的字段。(因为窗口字节是4字节,最大为65535,所以在选项字节中有一个窗口因子,是扩展了窗口大小的)。最后一部分,是不能发送的,接收端就是依靠这个窗口来控制发送端的速率,就是控制只能发送多少字节,后面的不能发送,等到接收到已经发送但未确定的数据,并返回ACK之后,发送端的窗口才继续往右移。所以这个叫做滑动窗口。

注意:TCP不支持窗口右边界左移。

每个TCP报文段都包含ACK号和窗口通告信息,TCP发送端可以据此调节窗口结构。窗口左边界不能左移,因为它控制的是已确认的ACK号,具有累积性,不能返回。当得到的ACK号增大而窗口大小保持不变时(通常如此)。我们就说窗口向前“滑动”。若随着ACK号增大窗口却减小,则左右边界距离减小。当左右边界相等时,称之为**“零窗口”**。此时发送发送端不能再发送新数据。这种情况下,TCP发送端开始探测(probe)对方窗口,伺机增大提供窗口。

5.2.2 接收窗口

接收端也维护了一个窗口结构,但比发送端窗口简单。
在这里插入图片描述
接收窗口包含了3个部分,第一部分已接收并确认的数据,第二部分,接收后将会保存的数据,该窗口可以保证其接收数据的正确性,特别是,避免存储重复的已接收和确认数据,也可以避免存储不应该接收的数据(超过发送方右窗口边界的数据)、第三部分就是不能接收的数据。

注意:由于TCP的累积ACK结构,只有当到达数据序列号等于左边界时,数据才不会被丢弃,窗口才能向前滑动。对选择确认TCP来说,使用SACK选项,窗口内的其他报文段也可以被接收确认,但只有在接收到等于左边界的序列号数据时,窗口才能前移。

5.2.3 零窗口与TCP持续计时器

我们在前面了解到,TCP是通过接收端的通告窗口来实现流量控制的。通告窗口指示了接收端可接收的数据量。当窗口值变为0时,可以有效的阻止发送端继续发送,直到窗口大小恢复为非零值。

当接收端重新获得可用空间时,会给发送端传输一个窗口更新,告知发送端可以继续发送数据了,但是这样的窗口更新只是一个纯ACK,没有包含数据,所以如果出现了丢失,就不会发送重传。这样子的话,发送和接收两端都处于等待状态,会形成一个死锁。

为防止这种死锁发生,发送端会采用一个持续计时器间歇性的查询接收端,看其窗口是否已经增长。持续计时器会触发窗口探测的传输,强制要求接受端返回ACK(其中包含窗口信息),随后以指数时间间隔发送。

5.2.4 糊涂窗口综合征

看书看的比较糊涂,所以百度了一下,有一篇写的还可以:TCP-IP详解:糊涂窗口综合症(Silly Window syndrome)

这里就抄抄一下原因:
这个问题可以归结为小包的问题,就是由于发送端和接收端上的处理不一致,导致网络上产生很多的小包,之前也介绍过避免网络上产生过多小包的措施,比如Nagle算法。在滑动窗口机制下,如果发送端和接收端速率很不一致,也会产生这种比较犯傻的状态:发送方发送的数据,只要一个大大的头部,携带数据很少。

对于接收端来讲,如果接收很慢,一次接收1个字节或者几个字节,这个时候接收端 缓冲区很快就会被填满,然后窗口通告为0字节,这个时候发送端停止发送,应用程序收上去1个字节后,发出窗口通告为1字节,发送方收到通告之后,发出1个字节的数据,这样周而复始,传输效率会非常低。

同时如果发送端程序一次发送一个字节,虽然窗口足够大,但是发送仍是一个字节一个字节的传输,效率很低

解决方案:
接收端:

  • 不应该通告小的窗口值。(在窗口可增至一个全长的报文段MSS或者接收端缓存空间的一遍之前,不能通告比当前窗口更大的窗口)。
  • 延时ACK,和累积ACK。

发送端:

  • 不应该发送小的报文,而且需由nagle算法控制何时发送。

为了避免SWS问题,满足下面的条件才能传输报文段。

  • 全长(发送MSS字节)的报文段可以发送
  • 数据长度≥接收端通告过的最大窗口值的一半,可以发送
  • 某一个ACK不是目前期盼的(需要重发)
  • 禁用Nagle算法

现在的linux内核中的TCP算法是支持窗口自动调优的,以后有空再分析。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/C1033177205/article/details/108230013

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include<stdio.h>#include<string.h>#include<stdlib.h>#include<malloc.h>#include<iostream>#include<stack>#include<queue>using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签