第22章 TCP的坚持定时器

所属:TCP/IP详解 卷1:协议 来源:TCP/IP详解 卷1:协议

本章介绍TCP的坚持定时器,包括窗口大小为0的情况、窗口探查和糊涂窗口综合征的避免等。


22.1 引言

坚持定时器

坚持定时器(Persist Timer):

  • 也叫持续定时器
  • 处理窗口大小为0的情况
  • 防止窗口更新丢失
  • 定期探查窗口大小

坚持定时器处理窗口为0的情况。


为什么需要坚持定时器

为什么需要坚持定时器:

场景:

  1. 接收方缓冲区满了
  2. 接收方发窗口大小为0的ACK
  3. 发送方停止发送
  4. 后来接收方应用读了数据,有空间了
  5. 接收方发窗口更新(窗口变大了)
  6. 但是这个窗口更新丢了!
  7. 发送方以为窗口还是0
  8. 接收方以为发送方知道窗口变大了
  9. 双方都等,死锁了!

问题:

  • 窗口更新是普通的ACK
  • 不可靠,不重传
  • 丢了就麻烦了
  • 会死锁

解决:

  • 坚持定时器
  • 发送方定期发窗口探查
  • 问接收方窗口有没有变大
  • 防止死锁

防止窗口更新丢失导致死锁。


本章讨论的内容

本章讨论的内容:

  • 窗口大小为0的情况
  • 坚持定时器的作用
  • 窗口探查
  • 糊涂窗口综合征的避免
  • 坚持定时器的时间

本章介绍坚持定时器。


22.2 窗口大小为0

什么时候窗口为0

什么时候窗口大小为0:

  • 接收方缓冲区满了
  • 应用还没读数据
  • 接收方告诉发送方窗口是0
  • 发送方停止发送

缓冲区满了窗口就为0。


发送方的反应

发送方收到窗口为0的ACK:

  • 停止发送数据
  • 等窗口变大
  • 启动坚持定时器
  • 定期探查

窗口为0就停止发送。


窗口更新

窗口更新(Window Update):

  • 接收方应用读了数据
  • 缓冲区有空间了
  • 接收方发窗口更新
  • 告诉发送方窗口变大了
  • 发送方可以继续发了

问题:

  • 窗口更新是纯ACK
  • 不携带数据
  • 不可靠
  • 丢了不重传
  • 会出问题

窗口更新可能丢。


22.3 坚持定时器的工作

坚持定时器的作用

坚持定时器的作用:

  • 窗口为0时启动
  • 定期发窗口探查
  • 问接收方窗口有没有变大
  • 防止窗口更新丢失导致死锁

定期探查窗口大小。


窗口探查

窗口探查(Window Probe):

  • 发送方发一个字节的数据
  • 就一个字节
  • 问接收方窗口多大
  • 接收方回ACK,带窗口大小

为什么发一个字节:

  • 即使窗口是0
  • 也可以发一个字节探查
  • 接收方必须回应
  • 这样就能知道窗口大小了

发一个字节探查窗口。


探查的过程

探查的过程:

  1. 发送方收到窗口为0的ACK

    • 停止发送
    • 启动坚持定时器
  2. 定时器到了

    • 发窗口探查(1字节)
    • 重置定时器
  3. 收到ACK

    • 窗口还是0:继续等
    • 窗口变大了:可以发数据了,关闭定时器
  4. 没收到ACK

    • 定时器到了再发
    • 指数退避

定期发探查。


坚持定时器的时间

坚持定时器的时间:

  • 初始通常是5秒
  • 然后指数退避
  • 5秒, 10秒, 20秒, 40秒…
  • 最长一般是60秒

为什么指数退避:

  • 避免太多探查包
  • 网络可能拥塞
  • 退避减少负担

坚持定时器指数退避。


22.4 糊涂窗口综合征

什么是糊涂窗口综合征

糊涂窗口综合征(Silly Window Syndrome, SWS):

  • 窗口一点点变大
  • 发送方就发一点点数据
  • 全是小包
  • 效率极低
  • 窗口小得可笑,所以叫糊涂

糊涂窗口综合征就是全是小包。


坚持定时器和SWS

坚持定时器和SWS的关系:

  • 接收方窗口一点点增加
  • 每次增加一点就发窗口更新
  • 发送方收到就发一点点数据
  • 这样就SWS了

坚持定时器能避免吗:

  • 不能完全避免
  • 但发送方的坚持定时器
  • 会等一会儿再发
  • 可能攒多点再发
  • 有一定帮助

坚持定时器对SWS有一定帮助。


接收方避免SWS

接收方怎么避免SWS:

  • 不要窗口增加一点就通告
  • 等窗口增加到一定程度再通告
    • 至少一个MSS
    • 或者缓冲区的一半
  • 这样发送方才能发大包
  • 效率才高

为什么:

  • 小窗口通告了也没用
  • 发小包效率低
  • 不如等大点再通告

接收方等窗口够大了再通告。


发送方避免SWS

发送方怎么避免SWS:

  • Nagle算法
  • 不要有一点数据就发
  • 攒够了再发
  • 或者等ACK

为什么:

  • 小包效率低
  • 攒够了发大包
  • 效率高

发送方用Nagle算法避免。


22.5 小结

坚持定时器概述

  1. 什么是坚持定时器

    • 也叫持续定时器
    • 处理窗口为0的情况
    • 防止窗口更新丢失
  2. 为什么需要

    • 窗口更新可能丢
    • 会导致死锁
    • 定期探查

窗口大小为0

  1. 什么时候窗口为0

    • 接收方缓冲区满了
    • 应用没读数据
  2. 发送方反应

    • 停止发送
    • 启动坚持定时器
  3. 窗口更新

    • 接收方有空间了发更新
    • 可能丢,不可靠

坚持定时器的工作

  1. 窗口探查

    • 发一个字节
    • 问窗口多大
    • 接收方必须回应
  2. 过程

    • 窗口为0启动定时器
    • 到了发探查
    • 收到ACK看窗口
    • 没收到再发
  3. 时间

    • 初始5秒左右
    • 指数退避
    • 最长60秒

糊涂窗口综合征

  1. 什么是SWS

    • 窗口一点点变大
    • 发一点点数据
    • 全是小包
    • 效率低
  2. 接收方避免

    • 等窗口够大再通告
    • 至少一个MSS
    • 或缓冲区一半
  3. 发送方避免

    • Nagle算法
    • 攒够了再发

关键概念

  1. 坚持定时器

    • 窗口为0时用
    • 防止死锁
  2. 窗口探查

    • 发一个字节
    • 问窗口大小
  3. 指数退避

    • 探查间隔越来越长
  4. 糊涂窗口综合征

    • 小窗口小包
    • 双方都要避免

TCP定时器