以字节为单位的滑动窗口
- TCP 使用流水线传输和滑动窗口协议实现高效、可靠的传输。
- TCP 的滑动窗口是以字节为单位的。
- 发送方 A 和接收方 B 分别维持一个发送窗口和一个接收窗口。
- 发送窗口表示:在没有收到确认的情况下,可以连续把窗口内的数据全部发送出去。
- 接收窗口表示:只允许接收落入窗口内的数据。
根据 B 给出的窗口值,A 构造出自己的发送窗口。
发送窗口表示:在没有收到 B 的确认的情况下,A 可以连续把窗口内的数据都发送出去。
发送窗口里面的序号表示允许发送的序号。
显然,窗口越大,发送方就可以在收到对方确认之前连续发送更多的数据,因而可能获得更高的传输效率。
发送缓存
发送方的应用进程把字节流写入 TCP 的发送缓存。
接收缓存
接收方的应用进程从 TCP 的接收缓存中读取字节流。
发送缓存与接收缓存的作用
- 发送缓存用来暂时存放:
- 发送应用程序传送给发送方 TCP 准备发送的数据;
- TCP 已发送出但尚未收到确认的数据。
- 接收缓存用来暂时存放:
- 按序到达的、但尚未被接收应用程序读取的数据;
- 不按序到达的数据。
需要注意:
第一,A 的发送窗口并不总是和 B 的接收窗口一样大(因为有一定的时间滞后)。
第二,TCP 标准没有规定对不按序到达的数据应如何处理。通常是先临时存放在接收窗口中,等到字节流中所缺少的字节收到后,再按序交付上层的应用进程。
第三,TCP 要求接收方必须有累积确认的功能,这样可以减小传输开销。
接收方发送确认
- 接收方可以在合适的时候发送确认,也可以在自己有数据要发送时把确认信息顺便捎带上。
- 但请注意两点:
- 第一,接收方不应过分推迟发送确认,否则会导致发送方不必要的重传,这反而浪费了网络的资源。。
- 第二,捎带确认实际上并不经常发生,因为大多数应用程序很少同时在两个方向上发送数据。
超时重传时间的选择
重传机制是 TCP 中最重要和最复杂的问题之一。
TCP 每发送一个报文段,就对这个报文段设置一次计时器。
只要计时器设置的重传时间到但还没有收到确认,就要重传这一报文段。
重传时间的选择是 TCP 最复杂的问题之一。
往返时延的方差很大
由于 TCP 的下层是一个互联网环境,IP 数据报所选择的路由变化很大。因而运输层的往返时间 (RTT) 的方差也很大。
TCP 超时重传时间设置
- 如果把超时重传时间设置得太短,就会引起很多报文段的不必要的重传,使网络负荷增大。
- 但若把超时重传时间设置得过长,则又使网络的空闲时间增大,降低了传输效率。
- TCP 采用了一种自适应算法,它记录一个报文段发出的时间,以及收到相应的确认的时间。这两个时间之差就是报文段的往返时间 RTT。
加权平均往返时间
TCP保留了RTT的一个加权平均往返时间RTTS(这又称为平滑的往返时间)。
第一次测量到 RTT 样本时,RTTS 值就取为所测量到的 RTT 样本值。以后每测量到一个新的 RTT 样本,就按下式重新计算一次 RTTS:
新的RTTS = (1 - α) × (旧的RTTS) + α × (新的RTT样本)
式中,0 ≤ α <1。若 α 很接近于零,表示 RTT 值更新较慢。若选择 α 接近于 1,则表示 RTT 值更新较快。
RFC 6298 推荐的 α 值为 1/8,即 0.125。
超时重传时间 RTO
- RTO (Retransmission Time-Out) 应略大于上面得出的加权平均往返时间 RTTS。
- RFC 6298 建议使用下式计算 RTO:
- RTO = RTTS + 4 × RTTD (5-5)
- RTTD 是 RTT 的偏差的加权平均值。
- RFC 6298 建议这样计算RTTD 。第一次测量时, RTTD 值取为测量到的 RTT 样本值的一半。在以后的测量中,则使用下式计算加权平均的 RTTD :
新的 RTTD = (1 - β ) × (旧的RTTD) + β × | RTTS - 新的 RTT 样本|
- β是个小于 1 的系数,其推荐值是 1/4,即 0.25。
往返时间 (RTT) 的测量相当复杂
- TCP 报文段 1 没有收到确认。重传(即报文段 2)后,收到了确认报文段 ACK。
- 如何判定此确认报文段是对原来的报文段 1 的确认,还是对重传的报文段 2 的确认?
Karn 算法
- 在计算平均往返时间 RTT 时,只要报文段重传了,就不采用其往返时间样本。
- 这样得出的加权平均平均往返时间 RTTS 和超时重传时间 RTO 就较准确。
- 但是,这又引起新的问题。当报文段的时延突然增大了很多时,在原来得出的重传时间内,不会收到确认报文段。于是就重传报文段。但根据 Karn 算法,不考虑重传的报文段的往返时间样本。这样,超时重传时间就无法更新。
修正的 Karn 算法
报文段每重传一次,就把 RTO 增大一些:
新的 RTO = γ × (旧的 RTO)系数 γ 的典型值是 2 。
当不再发生报文段的重传时,才根据报文段的往返时延更新平均往返时延 - RTT 和超时重传时间 RTO 的数值。
实践证明,这种策略较为合理。
选择确认 SACK
- 问题:若收到的报文段无差错,只是未按序号,中间还缺少一些序号的数据,那么能否设法只传送缺少的数据而不重传已经正确到达接收方的数据?
- 答案是可以的。选择确认 SACK (Selective ACK) 就是一种可行的处理方法。
TCP 的接收方在接收对方发送过来的数据字节流的序号不连续,结果就形成了一些不连续的字节块。
和前后字节不连续的每一个字节块都有两个边界:边界和右边界。
- 第一个字节块的左边界 L1 = 1501,但右边界 R1 = 3001。左边界指出字节块的第一个字节的序号,但右边界减 1 才是字节块中的最后一个序号。
- 第二个字节块的左边界 L2 = 3501,而右边界 R2 = 4501。
RFC 2018 的规定
- 如果要使用选择确认,那么在建立 TCP 连接时,就要在 TCP 首部的选项中加上“允许 SACK”的选项,而双方必须都事先商定好。
- 如果使用选择确认,那么原来首部中的“确认号字段”的用法仍然不变。只是以后在 TCP 报文段的首部中都增加了 SACK 选项,以便报告收到的不连续的字节块的边界。
- 由于首部选项的长度最多只有 40 字节,而指明一个边界就要用掉 4 字节,因此在选项中最多只能指明 4 个字节块的边界信息。