【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