第19章 TCP:数据流

所属:TCP/IP详解 卷2:实现 来源:TCP/IP详解 卷2:实现

本章描述TCP数据流的处理,包括序号、确认、滑动窗口、流量控制和数据的收发等。


19.1 引言

TCP数据流的特点

TCP数据流的特点:

  • 面向字节流
  • 没有边界
  • 应用看到的是连续的字节流
  • 可靠、有序
  • 流量控制

TCP是面向字节流的协议。


本章讨论的内容

本章讨论的内容:

  • 序号和确认号
  • 滑动窗口
  • 流量控制
  • 数据的发送
  • 数据的接收
  • 紧急数据

本章讨论TCP数据流的处理。


19.2 序号和确认号

序号

序号(Sequence Number):

  • 本报文段数据的第一个字节的序号
  • 32位
  • 循环使用
  • 建立连接时初始序号(ISN)随机

为什么需要序号:

  • 标识每个字节
  • 保证顺序
  • 去重
  • 确认

序号是字节流的编号。


确认号

确认号(Acknowledgment Number):

  • 期望收到的下一个字节的序号
  • 表示这个序号之前的都收到了
  • 32位
  • 累积确认

累积确认:

  • 确认到某个序号
  • 之前的都收到了
  • 中间没有丢的

确认号是累积的。


序号空间

序号空间:

  • 32位,约40亿
  • 循环使用
  • 最大段生命期(MSL)内不会回绕
  • 高速网络可能有问题(PAWS解决)

序号是循环的。


19.3 滑动窗口

什么是滑动窗口

滑动窗口(Sliding Window):

  • 流量控制的机制
  • 接收方通告窗口大小
  • 发送方最多发窗口大小的数据
  • 窗口随着确认滑动

滑动窗口实现流量控制。


发送方的窗口

发送方的窗口结构:

已确认     已发送未确认      可发送       不可发送
<---------><---------------><-----------><--------------->
          ^               ^            ^
          |               |            |
         SND.UNA      SND.NXT     SND.UNA + SND.WND

三个部分:

  1. 已确认:已经收到ACK的
  2. 已发送未确认:发了还没收到ACK
  3. 可发送:窗口内还没发的
  4. 不可发送:窗口外的

发送方的窗口分为几个部分。


接收方的窗口

接收方的窗口结构:

已接收已确认    可接收      不可接收
<-------------><-----------><------------->
               ^          ^
               |          |
            RCV.NXT  RCV.NXT + RCV.WND

两个部分:

  1. 已接收已确认:已经收到并确认了
  2. 可接收:窗口内的,可以接收
  3. 不可接收:窗口外的,丢弃

接收方的窗口决定能收多少。


窗口的滑动

窗口的滑动:

  • 收到新的数据,确认号增加
  • 窗口向右滑动
  • 可以接收更多的数据
  • 发送方收到ACK,窗口也向右滑

窗口随着数据的收发滑动。


19.4 流量控制

什么是流量控制

流量控制(Flow Control):

  • 防止发送方发得太快
  • 接收方处理不过来
  • 接收方通告窗口大小
  • 发送方不能超过窗口

流量控制防止接收方被淹没。


窗口大小的通告

窗口大小的通告:

  • 每个ACK都带窗口大小
  • 接收方根据自己的缓冲区调整
  • 缓冲区大,窗口大
  • 缓冲区小,窗口小

窗口大小的单位:

  • 字节
  • 16位字段,最大65535
  • 窗口扩大选项可以更大

窗口大小在TCP首部中通告。


零窗口

零窗口(Zero Window):

  • 接收方缓冲区满了
  • 通告窗口为0
  • 发送方不能再发数据
  • 等窗口恢复

零窗口的问题:

  • 死锁风险
  • 窗口恢复的ACK丢了
  • 两边都等
  • 坚持定时器解决

零窗口可能导致死锁,坚持定时器解决。


糊涂窗口综合征

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

  • 窗口很小就发送
  • 每个段只有很少的数据
  • 效率很低
  • 40字节首部 + 1字节数据
  • 开销太大

怎么避免:

  • 接收方:窗口小就不通告
  • 发送方:数据少就不发
  • 等窗口大一点或数据多一点

避免小窗口,提高效率。


19.5 数据的发送

发送缓冲区

发送缓冲区:

  • 应用写入的数据
  • 还没发送的
  • 发了没确认的
  • 都在缓冲区里

发送缓冲区的大小:

  • 可以设置
  • 影响最大窗口
  • 不能超过对端的窗口

发送缓冲区缓存待发送和未确认的数据。


什么时候发送

TCP发送数据的时机:

  1. MSS满了

    • 数据够一个最大段
    • 立即发送
  2. 应用推送

    • 应用设置PSH
    • 立即发送
  3. Nagle算法超时

    • 等了一会
    • 还是不够一个MSS
    • 发送
  4. 需要确认

    • 收到ACK,窗口打开
    • 可以发新数据

不是应用写了就立即发。


Nagle算法

Nagle算法:

  • 防止大量小报文
  • 只有一个未确认的小报文
  • 等ACK回来再发下一个
  • 或者等数据够一个MSS

为什么需要:

  • 交互式应用
  • 每次发1字节
  • 40字节首部 + 1字节数据
  • 效率太低

Nagle算法减少小报文。


延迟ACK

延迟ACK(Delayed ACK):

  • 不收到数据就立即发ACK
  • 等一会
  • 可能有数据要发,捎带ACK
  • 减少报文数量

延迟多久:

  • 通常200ms
  • 最多等2个段
  • 超时就发

延迟ACK减少ACK数量。


19.6 数据的接收

接收缓冲区

接收缓冲区:

  • 收到的数据
  • 还没被应用读取的
  • 按序号排序
  • 可能有间隙(乱序)

接收缓冲区的大小:

  • 可以设置
  • 决定窗口大小
  • 窗口 = 缓冲区 - 已接收未读取

接收缓冲区缓存收到的数据。


乱序数据的处理

乱序数据的处理:

  • 收到的段不是按顺序的
  • 先缓存起来
  • 等前面的到了再一起交给应用
  • 重复的ACK(确认最后一个有序的)

为什么要缓存乱序:

  • 网络可能乱序
  • 不一定是丢了
  • 缓存起来可以避免重传
  • 提高效率

乱序数据先缓存,不丢弃。


数据的上交

数据交给应用:

  • 按顺序
  • 连续的数据
  • 应用用read等读取
  • 从缓冲区复制到应用空间

什么时候上交:

  • 数据连续
  • 应用在读
  • 或者有推送标志

按顺序交给应用。


19.7 紧急数据

什么是紧急数据

紧急数据(Urgent Data):

  • 也叫带外数据(Out-of-Band, OOB)
  • 优先级高
  • 不需要等前面的数据
  • 可以提前通知接收方

怎么表示:

  • URG标志
  • 紧急指针
  • 指向紧急数据的最后一个字节

紧急数据优先级高。


紧急数据的处理

发送方:

  • 设置URG标志
  • 设置紧急指针
  • 可以在窗口外发送
  • 立即发送

接收方:

  • 收到URG标志
  • 通知应用有紧急数据
  • 应用可以读取
  • 正常数据还是按顺序

紧急数据只是通知,数据还是按顺序。


紧急数据的问题

紧急数据的问题:

  • 实现不一致
  • 有的实现是1字节,有的是多字节
  • 有的是通知,有的是真正带外
  • 应用要小心使用

紧急数据的实现有差异。


19.8 小结

序号和确认

  1. 序号

    • 每个字节的编号
    • 32位循环
    • 初始序号随机
  2. 确认号

    • 期望的下一个序号
    • 累积确认
    • 之前的都收到了

滑动窗口

  1. 发送方窗口

    • 已确认
    • 已发送未确认
    • 可发送
    • 不可发送
  2. 接收方窗口

    • 已接收已确认
    • 可接收
    • 不可接收
  3. 窗口滑动

    • 随着确认滑动
    • 流量控制

流量控制

  1. 窗口通告

    • 每个ACK带窗口
    • 接收方控制
  2. 零窗口

    • 缓冲区满了
    • 不能发了
    • 坚持定时器防止死锁
  3. 糊涂窗口综合征

    • 避免小窗口
    • 提高效率

数据发送

  1. 发送缓冲区

    • 缓存待发送和未确认的
  2. 发送时机

    • MSS满了
    • 应用推送
    • Nagle超时
    • 收到ACK
  3. Nagle算法

    • 防止小报文
    • 提高效率
  4. 延迟ACK

    • 减少ACK数量
    • 捎带确认

数据接收

  1. 接收缓冲区

    • 缓存收到的数据
  2. 乱序处理

    • 先缓存
    • 等前面的到了
  3. 数据上交

    • 按顺序
    • 应用读取

紧急数据

  1. 作用

    • 高优先级
    • 提前通知
  2. 处理

    • URG标志
    • 紧急指针
    • 通知应用
  3. 问题

    • 实现不一致
    • 小心使用

关键概念

  1. 字节流

    • 面向字节
    • 没有边界
  2. 滑动窗口

    • 流量控制
    • 窗口滑动
  3. 序号和确认

    • 字节编号
    • 累积确认
  4. Nagle算法

    • 减少小报文
  5. 延迟ACK

    • 减少ACK数量
  6. 紧急数据

    • 带外数据
    • 高优先级

数据流