流量控制:

    1. TFTP使用了停止等待协议。数据发送方在发送下一个数据块之前需要等待接收对已发送数据的确认。
    2. 滑动窗口协议是另一种形式的流量控制方法。该协议允许发送方在停止并等待确认前可以连续发送多个分组。

    由于发送方不必每发一个分组就停下来等待确认,因此该协议可以加速数据的传输。

    多个分组发送的案例:

    1. 正常数据流

    image.png
    1. 报文段7、14和16中的ACK确认了两个收到的报文段
    2. 使用TCP的滑动窗口协议时,接收方不必确认每一个收到的分组。
    3. 在TCP中,ACK是累积的—它们表示接收方已经正确收到了一直到确认序号减1的所有字节。
    4. 报文段7、14三个数据确认的都是2048字节,而16报文段确认的是1024个字节。

    1. 快的发送方和慢的接收方

      image.png
      1. 发送方发送4个数据报文段(报文段 4-7)去填充接收方的窗口,然后停下来等待一个ACK。
      2. 接收方发送ACK(报文段8),但通告其窗口大小为0,这说明接收方已收到所有数据,但这些数据都在接收方的TCP缓冲区,
      因为应用程序还没有机会读取这些数据。
      3. 另一个ACK(报文段9,称为窗口更新)在17.4ms后发送,表明接收方现在可以接收另外的4096个字节的数据。
      虽然这看起来像一个ACK,但由于它并不确认任何新数据,只是用来增加窗口的右边沿,因此被称为窗口更新。
      4. 发送方发送最后4个报文段(10~13),再次填充了接收方的窗口。注意到报文段13中包括两个比特标志:PUSH和FIN。
      5. 随后从接收方传来另外两个ACK(14 ~ 16),它们确认了最后的4096字节的数据(从4097到8192字节)和FIN(标号为8192)

    滑动窗口
    image.png
    图20-4 TCP滑动窗口的可视化表示

    接收方通告的窗口称为提出的窗口(offered window):
    它覆盖了从第4字节到第9字节的区域,表明接收方已经确认了包括第3字节在内的数据,且通告窗口大小为6。
    发送方计算它的可用窗口,该窗口表明多少数据可以立即被发送。
    当接收方确认数据后,这个滑动窗口不时地向右移动。窗口两个边沿的相对运动增加或减少了窗口的大小。
    我们使用三个术语来描述窗口左右边沿的运动:
    image.png
    图20-5 窗口边沿的移动

    1. 称窗口左边沿向右边沿靠近为窗口合拢。这种现象发生在数据被发送和确认时,此时还没有被应用程序确认。
      2. 当窗口右边沿向右移动时将允许发送更多的数据,我们称之为窗口张开
      这种现象发生在另一端的接收进程读取已经确认的数据并释放了TCP的接收缓存时。
      3. 当右边沿向左移动时,我们称之为窗口收缩
      强烈建议不要使用这种方式。

    注意:
    1. 因为窗口的左边沿受另一端发送的确认序号的控制,因此不可能向左边移动。
    2. 如果接收到一个指示窗口左边沿向左移动的ACK,则它被认为是一个重复ACK
    3. 如果左边沿到达右边沿,则称其为一个零窗口,此时发送方不能够发送任何数据。

    窗口大小
    由接收方提供的窗口的大小通常可以由接收进程控制,这将影响TCP的性能。
    插口API允许进程设置发送和接收缓存的大小。接收缓存的大小是该连接上所能够通告的最大窗口大小。
    有一些应用程序通过修改插口缓存大小来增加性能。

    位于以太网上的两个工作站之间进行文件传输时,默认的4096字节并不是最理想的大小,
    将两个缓存增加到16384个字节可以增加约40%左右的吞吐量。

    PUSH标志
    发送方:
    发送方使用该PUSH标志通知接收方将所收到的数据全部提交给接收进程。
    通过允许客户应用程序通知其TCP设置PUSH标志,客户进程通知TCP在向服务器发送一个报文段时不要因等待额外数据而使已提交数据在缓存中滞留。
    接收方:
    当服务器的TCP接收到一个设置了PUSH标志的报文段时,它需要立即将这些数据递交给服务器进程而不能等待判断是否还会有额外的数据到达。

    慢启动
    当发送方和接收方处于同一个局域网时,发送方一开始便向网络发送多个报文段,直至达到接收方通告的窗口大小为止,这种方式是可以的。
    但是在广域网中如果在发送方和接收方之间存在多个路由器和速率较慢的链路时,就有可能出现一些问题。一些中间路由器必须缓存分组,并有可能耗尽存储器的空间。
    这种连接方式严重降低了TCP连接的吞吐量。

    TCP需要支持一种被称为“慢启动(slow start)”的算法。
    该算法通过观察到新分组进入网络的速率应该与另一端返回确认的速率相同而进行工作

    慢启动为发送方的TCP增加了另一个窗口:拥塞窗口(congestion window),记为cwnd

    当与另一个网络的主机建立TCP连接时,拥塞窗口被初始化为1个报文段(即另一端通告的报文段大小)。
    每收到一个ACK,拥塞窗口就增加一个报文段(cwnd以字节为单位,但是慢启动以报文段大小为单位进行增加)。
    发送方取拥塞窗口与通告窗口中的最小值作为发送上限。
    拥塞窗口(慢启动)是发送方使用的流量控制,而通告窗口则是接收方使用的流量控制。

    慢启动流程:
    1. 发送方开始时发送一个报文段,然后等待ACK。
    2. 当收到该ACK时,拥塞窗口从1增加为2,即可以发送两个报文段。
    3. 当收到这两个报文段的ACK时,拥塞窗口就增加为4。这是一种指数增加的关系。

    慢启动的例子:
    image.png
    图20-8 慢启动的例子

    1. 发送方发送一个长度为512字节的报文段,然后等待ACK。
      2. 该ACK在716 ms后收到。这个时间是一个往返时间的指示。
      3. 于是拥塞窗口增加了2个报文段,且又发送了两个报文段。
      4. 当收到报文段5的ACK后,拥塞窗口增加为3。
      此时尽管可发送多达3个报文段,可是在下一个ACK收到之前,只发送了2个报文段。