Loading

06-传输层(5)

可靠传输的实现及流量控制

1. 以字节为单位的滑动窗口

假定数据传输只在一个方向进行,即 A 发送数据,B 给出确认。现假定 A 收到了 B 发来的确认报文段,其中窗口是 20 字节,而确认号是 31(这表明 B 期望收到的下一个序号是 31,而序号 30 为止的数据已经收到了)。

发送窗口后沿的后面部分表示已发送且已收到了确认。这些数据显然不需要再保留了。而发送窗口前沿的前面部分表示不允许发送的,因为接收方都没有为这部分数据保留临时存放的缓存空间。


发送窗口的位置由 {窗口前沿和后沿位置} 共同确定

  • 后沿的变换 // 不可能向后移动,因为不能撤销掉已收到的确认
    • 不动(没有收到新的确认)
    • 前移(收到了新的确认)
  • 前沿的变化
    • 前移
    • 不动(情况1:没收到新的确认,对方通知的窗口大小也不变;情况2:收到了新的确认但对方通知的窗口缩小了,使得发送窗口前沿正好不动)



  • Tips
    • A 的发送窗口并不总是和 B 的接收窗口一样大(因为有一定的时间滞后)
    • 标准没有规定对不按序到达的数据应如何处理,通常是先临时存放在接收窗口中,等到字节流中所缺少的字节收到后,再按序交付上层的应用进程 // 选择确认 SACK (Selective ACK)
    • TCP 要求接收方必须有累积确认的功能,这样可以减小传输开销
  • 接收方发送确认
    • 接收方可以在合适的时候发送确认,也可以在自己有数据要发送时把确认信息顺便捎带上
    • 接收方不应过分推迟发送确认,否则会导致发送方不必要的重传,这反而浪费了网络的资源
    • 捎带确认实际上并不经常发生,因为大多数应用程序很少同时在两个方向上发送数据

2. 发送缓存&接收缓存

  • 发送缓存:发送方的应用进程把字节流写入 TCP 的发送缓存
    • 存放发送应用程序传送给发送方 TCP 准备发送的数据
    • 存放 TCP 已发送出但尚未收到确认的数据
  • 接收缓存:接收方的应用进程从 TCP 的接收缓存中读取字节流
    • 存放按序到达的、但尚未被接收应用程序读取的数据
    • 存放不按序到达的数据

3. 流量控制

3.1 引入

  • 一般说来,我们总是希望数据传输得更快一些。但如果发送方把数据发送得过快,接收方就可能来不及接收,这就会造成数据的丢失。
  • 流量控制(flow control) 就是让发送方的发送速率不要太快,既要让接收方来得及接收,也不要使网络发生拥塞。
  • 利用滑动窗口机制可以很方便地在 TCP 连接上实现流量控制

3.2 举例

3.3 持续计时器

a. "死锁"场景

  • B 向 A 发送了 0 窗口的报文段后不久,B 的接收缓存又有了一些存储空间。于是 B 向 A 发送了 rwnd = 400 的报文段
  • 但这个报文段在传送过程中丢失了。A 一直等待收到 B 发送的非零窗口的通知,而 B 也一直等待 A 发送的数据
  • 如果没有其他措施,这种互相等待的死锁局面将一直延续下去

b. 解决"死锁"

  • TCP 为每一个连接设有一个持续计时器
  • 只要 TCP 连接的一方收到对方的零窗口通知,就启动该持续计时器
  • 若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带 1 字节的数据),而对方就在确认这个探测报文段时给出了现在的窗口值
  • 若窗口不是 0,则死锁的僵局就可以打破了

4. 传输效率

可以用不同的机制来控制 TCP 报文段的发送时机:

  1. TCP 维持一个变量,它等于最大报文段长度 MSS。只要缓存中存放的数据达到 MSS 字节时,就组装成一个 TCP 报文段发送出去
  2. 由发送方的应用进程指明要求发送报文段,即 TCP 支持的推送 (push) 操作
  3. 发送方的一个计时器期限到了,这时就把当前已有的缓存数据装入报文段(但长度不能超过 MSS)发送出去
posted @ 2020-09-07 18:29  tree6x7  阅读(170)  评论(0编辑  收藏  举报