• 【TCP/IP详解 卷一:协议】第二十章 TCP的成块数据流


    本章节主要内容:

    • ACK的累积
    • 滑动窗口协议(即 接收方TCP数据报缓存的大小)
    • 流量控制(慢启动 -发送方TCP的 拥塞窗口(cwnd) 以及接受方的 通告窗口)

    20.1 引言

    在教材的之前章节中可以看到 TFTP 使用了停止等待协议。数据发送方 在发送下一个数据块之前 需要等待接收 对已发送数据的确认。
    本章将介绍,TCP的流量控制方法:滑动窗口协议,该协议允许发送方在 停止并等待确认之前可以 连续发送多个分组,这加快了数据的传输。
    接下来介绍 TCP的PUSH标志,慢启动,最后是 成块数据流的吞吐量。

    20.2 正常数据流

    这一章节介绍的是,数据传输过程中,经受时延的确认问题。
    一般来说,发送端发送一个数据报之后,接收端都会发送一个 对这个数据报的确认。但是使用TCP的滑动窗口协议的时候,接收方不必对每一个接收的数据报进行确认。我们在上一个章节有提到过,捎带数据的ACK。这里我们要介绍的是,ACK的累积机制。
    在TCP中,ACK是累积的,它们表现为 接收方 已经正确接收了 一直到确认序号-1的所有字节。或者说,发送端会一直发送数据 直到接收端缓存已满(或者接近),而接收方对这些数据 只要以一个ACK的方式进行确认就可以了,类似前面的 经受时延的ACK。

    我们在线路上看到的分组顺序依赖于许多无法控制的因素:(1)发送方TCP的实现 (2)接收方TCP的实现 (3)接收端的进程读取数据(依赖于操作系统的调度) (4)网络的动态性(以太网的冲突和退避)

    快的发送方 和 慢的接收方

    窗口更新:并不用于确认任何数据,只是用来额外增加窗口的右边沿(滑动窗口机制 中的 窗口张开),因此被称做窗口更新。

    20.3 滑动窗口 (接收端TCP数据报缓冲区大小)

    接收方通告的窗口 称为 提供的窗口。
    窗口大小与确认序号是对应的(确认序号 -> 确认序号 + 窗口大小) ,发送方计算它的可用窗口,该窗口表明:多少数据可以立即被发送。

    从发送端来看,滑动窗口协议 就像由四个部分组成的时间轴:(从左到右)

    • (1)发送并已经确认的数据
    • (2)发送但尚未确认的数据
    • (3)尚未发送,但是 接收端已经做好了接收的准备。
    • (4)不能发送,接收端尚未做好准备的部分。

    滑动窗口三个术语

    1.窗口合拢:当窗口的左边沿 从左向右 靠近的时候,这种现象发生在 数据被发送和确认 的时候。
    2.窗口张开:当窗口的右边沿 向右边移动 的时候,这种现象发生在 接收端处理了数据 以后。
    3.窗口收缩:当窗口的右边沿 向左边移动 的时候,这种现象不常发生。

    如果收到一个 命令窗口的左边沿 向左边移动的 ACK,那么会被认为是一个重复的ACK,将被遗弃。

    如果窗口左边沿 到达 右边沿的位置,则称为一个零窗口,此时发送方不能发送任何数据。

    从例图P213 总结:
    (1)发送方不必发送一个全窗口大小的数据。
    (2)来自接收方的ACK 把窗口向右边滑动。因为窗口是相对确认序号的。
    (3)窗口的大小可以减小:通过窗口通告。但是窗口的右边沿不能向左边移动:即不允许窗口收缩。
    (4)接收方在发送一个ACK的时候不必等待 窗口被填满(或者说 TCP数据报缓存已满),比如经受时延的ACK。

    20.4 窗口大小

    窗口的大小是可以通过socket来制定的。
    对以太网而言,默认的4096字节并不是最理性的大小,将两个缓存增加到 16384个字节 可以增加约40%的吞吐量(单位时间成功传送数据的数量)。

    20.5 PUSH标志

    发送方使用这个标志通知接收方 将收到的数据 全部提交给 接收端的接收进程。这里的数据包括 和PUSH一起发送的数据 和接收端已经收到的 存储在缓存中的数据。
    对于发送端:客户程序 通知 发送方TCP 设置PUSH标志,通知:在向服务器发送一个报文段的时候 不要因为 等待 其他的额外数据 而使 即将发送的数据 在缓存中滞留。就是 马上发送 的意思。
    对于接收端:立即将这些数据(刚刚收到的 和 TCP缓存中的数据)递交给 服务器进程,而不能因为 等待 判断还有没有其他的额外数据到达。

    许多实现程序认为它已经过时了:一个好的TCP实现 能够自行决定何时设置这个标志。

    20.6 慢启动 流量控制算法

    -拥塞窗口 避免 中间路由的缓存空间 耗尽

    在教材的一些例子中,发送方一开始就向网络发送多个数据报文段,直到达到 通知窗口的大小为止。
    但是这样子做带来了一些问题:在发送方和接收方之间 存在多个路由器 或者是 速率较慢的链路(slip)的时候,中间路由器必须对这些 数据报文 进行缓存,这可能使存储器的空间耗尽。
    所以,TCP需要支持一种 慢启动(slow start) 的算法:该算法保证 观察到 新分组进入网络的速率 = 另外一端确认的速率。

    慢启动 为 发送方的TCP增加了另外一个窗口:拥塞窗口(congestion window),记为cwnd。
    与另外一个网络的主机 建立TCP连接 的时候,拥塞窗口初始化为一个报文段(允许发送一个报文段),每收到一个ACK,拥塞窗口 就增加一个报文段。 这是一个指数增加的关系。
    也就是说:min{拥塞窗口的值, 通告窗口的值} = 发送端在接收到确认的ACK之前 发送报文段的最多数量。

    拥塞窗口 是发送方的 流量控制,而 通告窗口 是接收方使用的流量控制。

    20.7 成块数据的吞吐量

    吞吐量 概念:单位时间内成功传送数据的数量

    本节主要介绍 窗口大小 窗口流量控制 以及慢启动 对传输成块数据的 TCP连接的吞吐量 的相互作用。
    往返时间RRT(Round-Trip Time)

    在刚刚开始的时候,发送方发送了一个报文段,由于此时处在慢启动中(拥塞窗口值 为1),必须等待接收端对该数据段的确认。

    通常发送一个分组的时间取决于两个因素:

    • (1)传播时延(由光的有限速率,传播设备的等待时间等引起)
    • (2)取决于 媒体速率 的 发送时延

    对于一个给定的两个接点之间的通路,传输时延一般是 固定的,而 发送时延 则取决于 分组的大小。
    在 速率慢的情况下 起主要作用的是 发送时延。 在 速率非常快的情况下 起主要作用的是 传播时延。

    当发送方收到ACK的时候,拥塞窗口的值就+1.
    TCP的自计时:由于接收方只在 数据到达的时候 才生成ACK,所以 发送方接收到ACK之间的间隔 与 数据到达接收方的间隔 是一致的。(然而在实际中,返回路径上的排队(拥塞)会改变ACK的到达率)

    在拥塞窗口的值足够大之后,发送方和接收方之间的管道(pipe)被填满,此时无论拥塞窗口和通告窗口的值为多少,管道都不能再容纳更多的数据。
    当接收方在某个时间段从网络上移走一个报文段,发送方就再发送一个报文段到网络上。
    它们就像一辆挤满人的公交车,只有有人下车,才能有其他人上车。
    但是不管有多少报文段填充了这个管道,返回路径上总是有相同数目的ACK,这就是理想的稳定状态。

    20.7.1 带宽时延乘积 -管道容量的计算

    可以计算的 管道容量(capacity) (bit) = 带宽(bandwidth) (b/s) x 往返时间RTT(round-trip time) (s)
    一般称为 带宽时延乘积。取决于 带宽 和 往返时间RTT,即 不管是 带宽还是时延 都会影响管道的容量。

    20.7.2 拥塞

    当数据到达一个大的管道(快速局域网LAN) 并向一个小的管道(慢的广域网) 发送的时候 就会发送拥塞。
    当多个输入流到达一个路由器,而 路由器的输出流 小于 这些输入流的总和 的时候也会发送拥塞。
    连接 大的管道 和 小的管道 的路由器,称为“瓶颈”。

    当 从较慢的管道 返回到 较快的管道时,数据分组 保持在 较慢管道中的间隔。类似的,返回的确认 之间的间隔也与 数据在最慢的链路上的间隔 一致。

    20.8 紧急方式

    TCP 提供了紧急方式,它告诉另外一端有些具有某种方式的 紧急数据 已经放置在普通的数据流中。而被告知的另外一端,由接收方决定如何处理。
    通过设置TCP报文段中的两个字段来使用紧急方式:URG 置为1,16bit 的紧急指针置为一个 正的偏移量。该偏移量必须与TCP首部的序号字段相加,以便得出紧急数据的最后一个字节。

    TCP必须通知接收进程,何时已经接收到一个紧急数据指针 以及 何时某个紧急数据指针还不在连接上,或者紧急指针是否在数据流里面向前移动。
    接收进程必须被告知 何时碰到了紧急数据指针。
    只要接收方在当前读取位置 和 紧急数据指针之间 有数据,就处在 紧急方式。

    TCP本身对紧急数据知之甚少,唯一信息就是 URG标志置1 和 紧急指针,其他交给应用程序处理。

    许多不正确的实现 错误的称它为 带外数据。这很容易和 TCP的紧急方式 造成混淆。

    紧急方式有什么用呢?
    -最常见的例子是:Telnet 和 Rlogin:当交互数据用户 键入中止键 的时候。
    Telnet 和 Rlogin 从 服务器到客户 使用紧急方式 是因为在这个方向上的数据流 很可能要被客户的TCP停止(通告了一个为0的通告窗口)。

    如果服务器进入了紧急方式,尽管不能发送数据,服务器的TCP也会发送紧急指针和URG标志。

    当客户多次进入紧急方式的时候,接收方只有一个紧急指针,每当对方有新的值到达的时候它就会被覆盖。所以如果有很重要的数据,必须被发送方以某种形式 特别标记

    2016/8/16

  • 相关阅读:
    __declspec(noinline)
    硬件遮挡查询
    #pragma pack(*) 与 __declspec(align(*))
    Interesting. 如何获取一个数组长度
    __declspec(novtable)
    如何将一个float的小数部分保存成RGBA4个8位的byte
    plain old C++ functions, base模板函数与特化的模板函数
    LeetCode 5: Longest Palindromic Substring
    LeetCode 335:Self Crossing 自交
    LeetCode 649:Dota2 Senate
  • 原文地址:https://www.cnblogs.com/qq952693358/p/5774561.html
Copyright © 2020-2023  润新知