美文网首页
TCP(III) 流量控制

TCP(III) 流量控制

作者: 小小小超子 | 来源:发表于2018-03-26 16:06 被阅读58次

TCP 数据流与窗口管理

交互式通信

ssh 是一个典型的交互式通信协议,它是加密了的,通常每次按键都会生成一个单独的包。另外,ssh 会在服务端对客户端输入的字符进行回显。因此,服务端收到数据包会先发送一个 ACK,然后发送一个回显报文,再由客户端发送对回显报文段的 ACK,如下左图。

image

但通常第二段和第三段可以合并来减少传输次数,这种方法称为捎带延时确认,如上右图。我们可以再来看看 wireshark 抓的包:

image

不难发现,这些包三个为一组,先是客户端(192.168.0.120)发送一个加密的包,然后收到服务端一个加密包,然后客户端回复一个 ACK。看一下服务端发过来的包:

image

可以看到,标志位的 ACK 置为了 1,ACK 值为 145,PSH 位也置为了 1(表明收到后立刻返回给应用层),并且数据段不为空,说明包含了回显的部分。很明显这里采用了捎带延时确认。

延时确认

在很多情况下,TCP 累计确认可以允许延迟一小会儿发送 ACK,以便结合相同方向的数据一起传送。但是显然,TCP 不能延时任意时长,通常建议:TCP 实现延迟应小于 500 ms,实践中延时应小于 200 ms。该延时值是可以配置的可选值如下:禁用延时,始终延时,每隔一个包回复一个 ACK,自动确认时间;默认值为 3。

Nagle 算法

通常在类似于 ssh 这样的应用里,每次传输的数据包非常小,称为微型报文,这些报文会造成相当高的传输代价。可以采用 Nagle 算法来解决这类问题。

Nagle 算法规定,当一个 TCP 连接有在传数据时,小的报文段(长度小于 SMSS)不会被发送,直到所有在传数据都收到 ACK。并且收到 ACK 后,会收集小数据并整合到一个报文段发送。

下图为 ssh 应用中没有开启 Nagle 算法(左图)和开启 Nagle 算法(右图)的差别。

<img src="http://image.littlechao.top/20180317121248000003.jpg" height="400px" >

可以看到,没有开启时,同一时刻有很多包在传输,并且有很多小包(tinygram),总体时间短,但是网络负担大。开启了 Nagle 算法时,同一时刻只有一个方向的传输,并且在合适的情况下,合并小包一起发送,时间较长,但传输次数少,网络负担小。

延时 ACK 与 Nagle 结合

无论是延迟 ACK 还是 Nagle 算法,其目的都是减少网络中传输的包,减轻网络负担。但是二者一起使用时,可能会出现问题。

考虑如下情况:客户端依次要发送一个全长报文段以及若干个小包,服务端收到第一个全长包,然后延迟发送 ACK(延时,或者期待第二个全长报文段到达),而客户端采用了 Nagle 算法,需要等到 ACK 到达才能继续发送。这样就会形成一个短暂的死锁,性能反而变差。所以在有些情况下,如 ssh ,可以禁用 Nagle 算法。

流量控制与窗口管理

每个 TCP 报文段的首部里都包含了一个窗口大小字段,该字段占 16 位,最大表示 65536,也就是 64 KB,但 TCP 选项中的窗口缩放选项可以让它表示更大的窗口。

一般来说每个连接的接收端会有一个大小固定的缓存,用来暂存发送端发来的数据,然后由应用程序读取。当应用程序来不及处理缓存数据,而发送方又不停的发送数据,超出缓存大小,就会造成数据丢失和不必要的重传。窗口大小字段用于 TCP 的流量控制,用于表示接收端可用缓存大小。

滑动窗口

发送窗口

每个 TCP 连接的两端都维护了一个发送窗口,结构如下:

<img src="http://www.tcpipguide.com/free/diagrams/tcpswwindows.png">

主要分四部分:已经发送并收到确认、已经发送但未收到确认、未发送但可以发送、未发送并且目前不能发送。第三部分称为可用窗口,第二部分和第三部分合称发送窗口。随着时间推移,窗口可以有几种运动:

  • 关闭:随着 ACK 到来,发送窗口左边界向右移,窗口减小。
  • 打开:窗口右边界右移,即接收方可用缓存增大,发送方可用窗口也就增大。
  • 收缩:右边界左移,主机不支持这种做法,但 TCP 必须能处理这种问题。
接收窗口

除了发送窗口,接收方还维护了一个接收窗口。

image

接收窗口结构简单,包括已经接收且已经回复 ACK、允许对方发送但还未收到、目前不允许对方发送的部分。

控制流程

接收方收到一个数据包后,返回一个 ACK,根据自己的可用接收缓存大小设置 ACK 报文里的窗口大小。发送方收到这个窗口通告后,根据可用窗口大小调整自己的发送窗口,以达到调节发送速率的目的。

零窗口与 TCP 持续计时器

当发送方不停发送,接收方又比较忙的时候,可能会导致可用窗口大小为 0。当出现零窗口时,发送方收到一个 ACK 报文,其中的窗口大小为零,那么就表示暂时不能发送数据。而当接收方应用程序开始处理收到的数据,使得接收缓存里又有了空间,但是我们知道,窗口通告是包含在 ACK 报文里的,没有收到新的数据,就没法发送窗口通告,这时就会造成死锁。

所以当出现零窗口时,发送方会采用一个持续计时器间歇地查询接收端是否有可用窗口,持续计时器会触发窗口探测(window probe)的传输。为了保证对方能够收到查询,我们必须要往数据段放一些数据,以保证超时重发,通常会放一个字节的数据 。接收方收到窗口探测后,会被强制返回一个 ACK,并且包含自己当前可用窗口大小(这个大小会有特殊情况)。注意这里采用指数退避来计算持续计时器的超时时间。

前面谈到,大量数据量较小的包会造成传输速度的下降,也会造成网络负担。当接收端可用缓存从 0 慢慢增大到一个较小的值,这时候收到一个窗口探测,为了避免发送较小的包,接收端可以仍然在 ACK 中回复一个零窗口。

image

糊涂窗口综合征

当发送方发送的报文大小不固定时,可能会出现糊涂窗口综合征(Silly Window Syndrome,SWS)。当出现该问题时,交换的报文数据段大小较小,耗费的资源较多。

TCP 连接两端都可能导致 SWS:当接收端的通告窗口较小(或者是还没等到窗口变得够大),或者发送端发送的包较小(或者是没有等待其他小数据组合成大数据包)。为了避免 SWS,发送方要遵循一定规则。

对于接收方:

  • 不应通告小的窗口值。在窗口增至 min(MSS,接收端缓存的一半) 之前,不能通告比当前窗口(可能为 0)更大的值

对于发送方,满足任意一个:

  • 全长报文段可以发送
  • 数据段长度 >= 最大窗口通告的一半
  • 该连接禁用 Nagle 算法
  • 没有未经确认的在传数据

大容量缓存与自动调优

在相似的环境下,较小的接收缓存的 TCP 应用吞吐性能会较低。很多 TCP 协议栈中上层应用不能指定接收缓存大小,由操作系统来指定一个固定的或者动态变化的值。

相关文章

  • TCP(III) 流量控制

    TCP 数据流与窗口管理 交互式通信 ssh 是一个典型的交互式通信协议,它是加密了的,通常每次按键都会生成一个单...

  • 2018-07-11

    tcp的运输控制分为tcp流量控制和tcp拥塞控制,这里先讲tcp的拥塞控制。 为了讲清楚tcp的拥塞控制,还是利...

  • TCP的流量控制与拥塞控制机制

    参考:滑动窗口TCP的流量控制和拥塞控制 1 流量控制 利用滑动窗口机制实施流量控制 TCP协议里窗口机制有2种:...

  • TCP那些事儿

    目录: TCP是什么TCP报文结构TCP连接过程TCP状态转移TCP流量控制 —— 滑动窗口TCP拥塞控制TCP可...

  • 为什么单一tcp难以将千兆网卡压满

    tcp协议流量控制

  • 传输层之TCP

    TCP报文结构 TCP特点 1、面向连接 2、可靠传输 3、流量控制 4、拥塞控制 TCP连接 ...

  • 细说TCP的可靠传输、流量控制、拥塞控制

    目录 TCP如何实现可靠传输? TCP如何实现流量控制?(滑动窗口) TCP如何实现拥塞控制?(慢开始、拥塞避免、...

  • TCP与UDP

    二三层网络传输 TCP TCP需要关注的5个问题 顺序问题 丢包问题 连接维护 流量控制 拥塞控制 TCP头文件,...

  • TCP三次握手(转)

    建立连接:理解:窗口和滑动窗口TCP的流量控制TCP使用窗口机制进行流量控制什么是窗口?连接建立时,各端分配一块缓...

  • 【技术】TCP 的固定窗口和滑动窗口

    固定窗口 ●TCP 还提供了流量控制机制。流量控制可以调整给定会话中源和目的之间的 数据流速,有助于保持 TCP ...

网友评论

      本文标题:TCP(III) 流量控制

      本文链接:https://www.haomeiwen.com/subject/pxprcftx.html