上一篇文章讲了协议栈内部的组成,以及客户端与服务器建立连接时协议栈是如何工作的,本章将具体讲一下TCP控制信息里的控制位--ACK。

【网络知识入门,探索一次网页请求的旅程(一)】 https://blog.csdn.net/ck784101777/article/details/103741398

【网络知识入门,探讨DNS服务器在网页请求中的作用(二)】 https://blog.csdn.net/ck784101777/article/details/103741398

【网络知识入门,何为协议栈(三)】https://blog.csdn.net/ck784101777/article/details/103746921

【网络知识入门,深入探索协议栈(四)】https://blog.csdn.net/ck784101777/article/details/103761880

目录

一、使用ACK确认网络包已经收到

二、网络传输缓慢的毒瘤:ACK等待时间


一、使用ACK确认网络包已经收到

1.数据包的序号和ack序列号

   

到这里,网络包已经装好数据并发往服务器了,但数据发送操作还没有结束。TCP 具备确认对方是否成功收到网络包,以及当对方没收到时进行重发的功能,因此在发送网络包之后,接下来还需要进行确认操作。 我们先来看一下确认的原理(下图)。

首先,TCP 模块在拆分数据时,会先算好每一块数据相当于从头开始的第几个字节,接下来在发送这一块数据时,将算好的字节数写在 TCP 头部中,“序号”字段就是派在这个用场上的。然后,发送数据的长度也需要告知接收方,不过这个并不是放在TCP 头部里面的,因为用整个网络包的长度减去头部的长度就可以得到数据的长度,所以接收方可以用这种方法来进行计算。有了上面两个数值, 我们就可以知道发送的数据是从第几个字节开始,长度是多少了。 通过这些信息,接收方还能够检查收到的网络包有没有遗漏。例如, 假设上次接收到第 1460 字节,那么接下来如果收到序号为 1461 的包,说明中间没有遗漏;但如果收到的包序号为 2921,那就说明中间有包遗漏了。像这样,如果确认没有遗漏,接收方会将到目前为止接收到的数据长度加起来,计算出一共已经收到了多少个字节,然后将这个数值写入 TCP头部的 ACK 号中发送给发送方。

简单来说,发送方说的是“现在发送的是从第 ×× 字节开始的部分,一共有 ×× 字节哦!”而接收方则回复说,“到第 ×× 字节之前的数据我已经都收到了哦!”这个返回 ACK 号的操作被称为确认响应,通过这样的方式,发送方就能够确认对方到底收到了多少数据。

然而,下图的例子和实际情况还是有些出入的。在实际的通信中, 序号并不是从 1 开始的,而是需要用随机数计算出一个初始值,这是因为 如果序号都从 1 开始,通信过程就会非常容易预测,有人会利用这一点来发动攻击。但是如果初始值是随机的,那么对方就搞不清楚序号到底是从 多少开始计算的,因此需要在开始收发数据之前将初始值告知通信对象。大家应该还记得在我们刚才讲过的连接过程中,有一个将 SYN 控制位设为 1 并发送给服务器的操作,就是在这一步将序号的初始值告知对方的。实际上,在将 SYN 设为 1 的同时,还需要同时设置序号字段的值,而这里的值就代表序号的初始值。

2.数据包的确认是双向的
       前面介绍了通过序号和 ACK 号来进行数据确认的思路,但仅凭这些还不够,因为我们刚刚只考虑了单向的数据传输,但 TCP 数据收发是双向的,在客户端向服务器发送数据的同时,服务器也会向客户端发送数据,因此必须要想办法应对这样的情况。不过,这其实也不难,上图中展示的客户端向服务器发送数据的情形,我们只要增加一种左右相反的情形就 可以了,如下图所示。首先客户端先计算出一个序号,然后将序号和数 据一起发送给服务器,服务器收到之后会计算 ACK 号并返回给客户端;相反地,服务器也需要先计算出另一个序号,然后将序号和数据一起发送给客户端,客户端收到之后计算 ACK 号并返回给服务器。
  

此外,如图所示,客户端和服务器双方都需要各自计算序号,因此双方需要在连接过程中互相告知自己计算的序号初始值。明白原理之后我们来看一下实际的工作过程(如下图)。首先,客户端在连接时需要计算出与从客户端到服务器方向通信相关的序号初始值,并将这个值发送给服务器(图①)。接下来,服务器会通过这个初始值计算出 ACK 号并返回给客户端(图②)。初始值有可能在通信过程中丢失,因此当服务器收到初始值后需要返回 ACK 号作为确认。同时,服务器也需要计算出与从服务器到客户端方向通信相关的序号初始值,并将这个值发送给客户端(图②)。接下来像刚才一样,客户端也需要根据服 务器发来的初始值计算出 ACK 号并返回给服务器(图 ③)。到这里,序号和 ACK 号都已经准备完成了,接下来就可以进入数据收发阶段了。数据收发操作本身是可以双向同时进行的,但 Web 中是先由客户端向服务器发送请求,序号也会跟随数据一起发送(图 ④)。然后,服务器收到数据后再返回 ACK 号(图 ⑤)。从服务器向客户端发送数据的过程则正好 相反(图 ⑥⑦)。

补充:数据包中途丢失怎么办?
    TCP 采用这样的方式确认对方是否收到了数据,在得到对方确认之前,发送过的包都会保存在发送缓冲区中。如果对方没有返回某些包对应 的 ACK 号,那么就重新发送这些包。 这一机制非常强大。通过这一机制,我们可以确认接收方有没有收到某个包,如果没有收到则重新发送,这样一来,无论网络中发生任何错误, 我们都可以发现并采取补救措施(重传网络包)。反过来说,有了这一机制,我们就不需要在其他地方对错误进行补救了。 因此,网卡、集线器、路由器都没有错误补偿机制,一旦检测到错误就直接丢弃相应的包。应用程序也是一样,因为采用 TCP 传输,即便发生一些错误对方最终也能够收到正确的数据,所以应用程序只管自顾自地发送这些数据就好了。不过,如果发生网络中断、服务器宕机等问题,那么 无论 TCP 怎样重传都不管用。这种情况下,无论如何尝试都是徒劳,因此 TCP 会在尝试几次重传无效之后强制结束通信,并向应用程序报错。

二、网络传输缓慢的毒瘤:ACK等待时间

1.一传一应答的方式
    前面说的只是一些基本原理,实际上网络的错误检测和补偿机制非常复杂。下面来说几个关键的点。
    首先是返回 ACK 号的等待时间(这个等待时间叫超时时间)。
    当网络传输繁忙时就会发生拥塞,ACK 号的返回会变慢,这时我们就必须将等待时间设置得稍微长一点,否则可能会发生已经重传了包之后, 前面的 ACK 号才姗姗来迟的情况。这样的重传是多余的,看上去只是多发一个包而已,但它造成的后果却没那么简单。因为 ACK 号的返回变慢大多是由于网络拥塞引起的,因此如果此时再出现很多多余的重传,对于本来就很拥塞的网络来说无疑是雪上加霜。那么等待时间是不是越长越好呢?也不是。如果等待时间过长,那么包的重传就会出现很大的延迟,也会导致网络速度变慢。 看来等待时间需要设为一个合适的值,不能太长也不能太短,但这谈何容易。根据服务器物理距离的远近,ACK 号的返回时间也会产生很大的波动,而且我们还必须考虑到拥塞带来的影响。
    例如,在公司里的局域网环境下,几毫秒就可以返回 ACK 号,但在互联网环境中,当遇到拥塞时需要几百毫秒才能返回 ACK 号也并不稀奇。正因为波动如此之大,所以将等待时间设置为一个固定值并不是一个好办法。因此,TCP 采用了动态调整等待时间的方法,这个等待时间是根据 ACK 号返回所需的时间来判断的。具体来说,TCP 会在发送数据的过程中持续测量 ACK 号的返回时间,如果 ACK 号返回变慢,则相应延长等待时间;相对地,如果 ACK 号马上就能返回,则相应缩短等待时间。
2.多传非固定应答方式:滑动窗口

    如下图所示,每发送一个包就等待一个 ACK 号的方式是最简单也最容易理解的,但在等待 ACK 号的这段时间中,如果什么都不做那实在太浪费了。为了减少这样的浪费,TCP 采用图b这样的滑动窗口方式来管理数据发送和 ACK 号的操作。所谓滑动窗口,就是在发送一个包之后,不等待 ACK号返回,而是直接发送后续的一系列包。这样一来,等待 ACK 号的这段时间就被有效利用起来了。
             
    虽然这样做能够减少等待 ACK 号时的时间浪费,但有一些问题需要注意。在一来一回方式中,接收方完成接收操作后返回 ACK 号,然后发送方收到 ACK 号之后才继续发送下一个包,因此不会出现发送的包太多接收方处理不过来的情况。但如果不等返回 ACK 号就连续发送包,就有可能会出现发送包的频率超过接收方处理能力的情况。
缓冲区溢出
    下面来具体解释一下。当接收方的 TCP 收到包后,会先将数据存放到接收缓冲区中。然后,接收方需要计算 ACK 号,将数据块组装起来还原成原本的数据并传递给应用程序,如果这些操作还没完成下一个包就到了也不用担心,因为下一个包也会被暂存在接收缓冲区中。如果数据到达的速率比处理这些数据并传递给应用程序的速率还要快,那么接收缓冲区中的数据就会越堆越多,最后就会溢出。缓冲区溢出之后,后面的数据就进不来了,因此接收方就收不到后面的包了,这就和中途出错的结果是一样的,也就意味着超出了接收方处理能力。
滑动窗口基本思路
     我们可以通过下面的方法来避免这种情况的发生。首先,接收方需要告诉发送方自己最多能接收多少数据,然后发送方根据这个值对数据发送操作进行控制,这就是滑动窗口方式的基本思路。关于滑动窗口的具体工作方式,还是看图更容易理解,如下图所示。在这张图中,接收方将数据暂存到接收缓冲区中并执行接收操作。当接收操作完成后,接收缓冲区中的空间会被释放出来,也就可以接收更多的数据了, 这时接收方会通过 TCP 头部中的窗口字段将自己能接收的数据量告知发送 方。这样一来,发送方就不会发送过多的数据,导致超出接收方的处理能力了。
TCP调优之滑动窗口缓冲区
     此外,单从图上看,大家可能会以为接收方在等待接收缓冲区被填满之前似乎什么都没做,实际上并不是这样。这张图是为了讲解方便,故意体现一种接收方来不及处理收到的包,导致缓冲区被填满的情况。实际上, 接收方在收到数据之后马上就会开始进行处理,如果接收方的性能高,处理速度比包的到达速率还快,缓冲区马上就会被清空,并通过窗口字段告知发送方。 还有,图中只显示了从右往左发送数据的操作,实际上和序号、 ACK 号一样,发送操作也是双向进行的。前面提到的能够接收的最大数据量称为窗口大小,它是 TCP 调优参数中非常有名的一个。

返回ACK和更新滑动窗口的时机

要提高收发数据的效率,还需要考虑另一个问题,那就是返回 ACK 号和更新窗口的时机。如果假定这两个参数是相互独立的,分别用两个单独的包来发送,结果会如何呢?

首先,什么时候需要更新窗口大小呢?

当收到的数据刚刚开始填入缓冲区时,其实没必要每次都向发送方更新窗口大小,因为只要发送方在每次发送数据时减掉已发送的数据长度就可以自行计算出当前窗口的剩余长度。因此,更新窗口大小的时机应该是接收方从缓冲区中取出数据传递给应用程序的时候。这个操作是接收方应用程序发出请求时才会进行的,而发送方不知道什么时候会进行这样的操作,因此当接收方将数据传递给应用程序,导致接收缓冲区剩余容量增加时,就需要告知发送方,这就是更新窗口大小的时机。

那么 ACK 号又是什么情况呢?

当接收方收到数据时,如果确认内容没有问题,就应该向发送方返回 ACK 号,因此我们可以认为收到数据之后马上就应该进行这一操作。如果将前面两个因素结合起来看,首先,发送方的数据到达接收方,在接收操作完成之后就需要向发送方返回 ACK 号,而再经过一段时间 ,当数据传递给应用程序之后才需要更新窗口大小。但如果根据这样的设计来实现,每收到一个包,就需要向发送方分别发送 ACK 号和窗口更新这两个单独的包。这样一来,接收方发给发送方的包就太多了,导致网络效率下降。

因此,接收方在发送 ACK 号和窗口更新时,并不会马上把包发送出去,而是会等待一段时间,在这个过程中很有可能会出现其他的通知操作, 这样就可以把两种通知合并在一个包里面发送了。

举个例子,在等待发送ACK 号的时候正好需要更新窗口,这时就可以把 ACK 号和窗口更新放在一个包里发送,从而减少包的数量。当需要连续发送多个 ACK 号时,也可以减少包的数量,这是因为 ACK 号表示的是已收到的数据量,也就是说,它是告诉发送方目前已接收的数据的最后位置在哪里,因此当需要连续发送 ACK 号时,只要发送最后一个 ACK 号就可以了,中间的可以全部省略。当需要连续发送多个窗口更新时也可以减少包的数量,因为连续发生窗口更新说明应用程序连续请求了数据,接收缓冲区的剩余空间连续增加。这种情况和 ACK 号一样,可以省略中间过程,只要发送最终的结果就可以了。

网络知识入门,深入了解ACK控制位,网络传输缓慢的毒瘤:ACK等待时间  (五)相关推荐

  1. 网络知识入门:路由器基础知识全接触

    网络知识入门:路由器基础知识全接触 发布时间:2008.05.29 07:01     来源:赛迪网    作者:月伴雨 路由器综述 路由器是互联网的主要节点设备.路由器通过路由决定数据的转发.转发策 ...

  2. 网络知识入门,什么是以太网包,TCP/IP包,MAC头部,IP头部以及TCP头部(六)

    目录 一.以太网包 二.协议栈中IP模块的工作方式 1.TCP委托IP模块 2.IP模块的工作方式 三.mac头部 四.何为以太网 1.以太网的定义 2.如何收发以太网包 3.以太网接收网络包详细 4 ...

  3. 网络知识入门,探讨DNS服务器在网页请求中的作用(二)

    上一篇文章讲到网络请求是基于http协议传输的,消息请求包含了"对什么"和"做什么操作",于是一个网页请求就这么发送出去了.但是在发送消息之前,我们还需要对域名 ...

  4. 网络知识入门,用户如何连接互联网,ADSL调制解调器的妙用,PPP上网的三种方式(十二)

    互联网与家庭网络的区别      互联网是一个遍布世界的巨大而复杂的系统,但其基本工作方式却出奇地简单.和家庭.公司网络一样,互联网也是通过路由器来转发包的, 而且路由器的基本结构和工作方式也并没有什 ...

  5. 网络知识入门,网络协议体系架构(一)

    1.常用网络知识目录 1)子网掩码.ip分段 .tcp三次握手四次切断.ip地址库,纯真库,自建ip库,ip寻址算法,ip寻址工具,dhcp,pppoe,udp协议 2)dns原理,相关网络命令,dn ...

  6. 网络知识入门,探索网络运营商的内部:NOC和POP,电话公司的通信线路租借服务(十三)

    POP和NOC POP:Point of Presense,中文一般叫作"接入点"      网络到达了网络运营商的路由器,将是如何工作的呢?.     路由器是互联网的入口.互联 ...

  7. 网络知识入门,路由器工作原理(十)

    路由器工作原理       路由器的转发的工作原理和交换机类似,也是通过查表判断包转发的目标.不过在具体的操作过程上,路由器和交换机是有区别的.因为路由器是基于 IP 设计的,而交换机是基于以太网设计 ...

  8. Java网络爬虫入门:第01课:网络爬虫原理

    引言 随着互联网的迅速发展,网络资源越来越丰富,信息需求者如何从网络中抽取信息变得至关重要.目前,有效的获取网络数据资源的重要方式,便是网络爬虫技术.简单的理解,比如您对百度贴吧的一个帖子内容特别感兴 ...

  9. 网络知识:46张图带你了解网络传输、WIFI、以太网协议和网络寻址

    一.线缆和Wi-Fi 首先我们需要知道,想要将设备连接到网络,有两种方式可供选择,那就是「有线和无线」. 相信大家对这两兄弟都不陌生了,有线连接从很早以前就出现了,最早可追溯到1960年代,有线网络使 ...

最新文章

  1. 编程能力如何突飞猛进?
  2. 为什么越来越多的程序员开始学机器学习?揭秘一个重要原因
  3. 类加载机制(整个过程详解)
  4. JAVA基础知识+基础代码
  5. windows操作系统_国产Linux操作系统体验:易用性不比Windows差,但输在这点上
  6. window下c语言c s通信,c++ Windows Socket实现最简单的C/S网络通信(TCP)
  7. 优秀的长截图标注工具:iShot for Mac中文免费
  8. 文章三 国家助学贷款-还款
  9. 1/4-36UNS-2A的螺纹
  10. 【C语言】abs()用法及其他绝对值函数
  11. GitHub 克隆加速
  12. STM32CuBeMX驱动舵机
  13. i12蓝牙耳机怎么设置成中文_windows10的蓝牙怎么打开?如何修复Windows 10中的蓝牙问题...
  14. VBA 2000年之后活期存款利息计算
  15. Vue代理解决生产环境跨域问题
  16. 欧洲央行行长:与“主流”货币政策理论商榷
  17. 无人机综合管理系统、设备管理、设备台账、零部件管理、故障维修、维护工单、飞控成员、飞行站点、飞行计划、飞行记录、运维管理、维护管理、人员管理、无人机管理、维修保养、配件管理、保养管理、团队管理
  18. 校园人员与车辆综合管理平台之服务端
  19. python打印数字倒三角形脸适合什么发型_脸型瘦的做什么发型好看 倒三角的脸型适合什么发型...
  20. 光环国际——如何将PRINCE2植入到组织当中?

热门文章

  1. 16.求两个数的最大公约数和最小公倍数
  2. 概率论与数理统计 第一章 概率论的基本概念 要点复习笔记
  3. SQLite数据库rowid
  4. C/C++编程学习 - 第1周 ⑦ 头文件、强制类型转换、递归
  5. Android 1000实例代码集结(一 )
  6. java图片管理系统_基于Java Web技术的图片管理系统的设计与实现.doc
  7. 帆软相同列合并_合并报表软件有哪些深受欢迎
  8. Elmedia Video Player Pro 7.15 中文版 强大的mac视频播放器
  9. html页面打印调用jqprint.js
  10. 如何利用人性七宗罪来做营销