跳到主要内容

2. 流

2. 流 (Streams)

QUIC 中的 stream 为应用提供轻量级的有序字节流抽象. stream 可以是 unidirectional, 也可以是 bidirectional.

可以通过发送数据来创建 stream. 与 stream 管理相关的其他过程, 即结束, 取消和管理 flow control, 都被设计为施加最小开销. 例如, 单个 STREAM frame (第 19.8 节) 可以打开一个 stream, 为其承载数据, 并关闭该 stream. stream 也可以长期存在, 持续整个 connection 生命周期.

stream 可以由任一 endpoint 创建, 可以与其他 stream 交错并发发送数据, 也可以被取消. QUIC 不提供任何机制来保证不同 stream 上字节之间的顺序.

在 flow control 约束和 stream limit 的限制下, QUIC 允许任意数量的 stream 并发运行, 并允许在任意 stream 上发送任意数量的数据; 见第 4 节.

2.1 流类型和标识符 (Stream Types and Identifiers)

stream 可以是 unidirectional 或 bidirectional. unidirectional stream 在一个方向承载数据: 从该 stream 的发起方到其 peer. bidirectional stream 允许在两个方向发送数据.

在 connection 内, stream 由一个数值标识, 称为 stream ID. stream ID 是一个 62-bit integer (0 到 2^62-1), 对 connection 上的所有 stream 唯一. stream ID 编码为 variable-length integer; 见第 16 节. QUIC endpoint MUST NOT 在一个 connection 内复用 stream ID.

stream ID 的最低有效 bit (0x01) 标识该 stream 的发起方. client 发起的 stream 具有偶数 stream ID (该 bit 设置为 0), server 发起的 stream 具有奇数 stream ID (该 bit 设置为 1).

stream ID 的第二低有效 bit (0x02) 区分 bidirectional stream (该 bit 设置为 0) 和 unidirectional stream (该 bit 设置为 1).

因此, stream ID 的两个最低有效 bit 将 stream 标识为四种类型之一, 如表 1 所示.

BitsStream Type
0x00Client-Initiated, Bidirectional
0x01Server-Initiated, Bidirectional
0x02Client-Initiated, Unidirectional
0x03Server-Initiated, Unidirectional

表 1: Stream ID 类型 (Stream ID Types)

每种类型的 stream 空间分别从最小值 (0x00 到 0x03) 开始; 每种类型的后续 stream 使用数值递增的 stream ID 创建. 如果乱序使用某个 stream ID, 则该类型中所有编号更低的 stream ID 对应的 stream 也会被打开.

2.2 发送和接收数据 (Sending and Receiving Data)

STREAM frame (第 19.8 节) 封装应用发送的数据. endpoint 使用 STREAM frame 中的 Stream ID 和 Offset 字段按顺序放置数据.

endpoint MUST 能够将 stream 数据作为有序字节流递送给应用. 递送有序字节流要求 endpoint 对任何乱序收到的数据进行缓冲, 直到已通告的 flow control limit.

QUIC 不对 stream 数据的乱序递送作出特定安排. 但是, 实现 MAY 选择向接收应用提供乱序递送数据的能力.

endpoint 可能多次在同一 stream offset 接收某个 stream 的数据. 已经接收的数据可以丢弃. 如果给定 offset 的数据被多次发送, 该数据 MUST NOT 改变; endpoint MAY 将在一个 stream 内同一 offset 收到不同数据视为 PROTOCOL_VIOLATION 类型的 connection error.

stream 是有序字节流抽象, 对 QUIC 可见的结构仅限于此. 在数据被传输, packet loss 后被重传, 或递送到接收方应用时, 不期望保留 STREAM frame 边界.

endpoint MUST NOT 在任何 stream 上发送数据, 除非确保该数据处于其 peer 设置的 flow control limit 内. 第 4 节详细描述 flow control.

2.3 流优先级 (Stream Prioritization)

如果分配给 stream 的资源得到正确优先级排序, stream multiplexing 会对应用性能产生显著影响.

QUIC 不提供交换优先级信息的机制. 相反, 它依赖从应用接收优先级信息.

QUIC 实现 SHOULD 提供方法, 使应用能够指示 stream 的相对优先级. 实现使用应用提供的信息来确定如何向 active stream 分配资源.

2.4 流上的操作 (Operations on Streams)

本文档不定义 QUIC API; 它改为定义一组应用协议可以依赖的 stream 功能. 应用协议可以假定 QUIC 实现提供一个接口, 其中包含本节描述的操作. 为特定应用协议设计的实现可能只提供该协议使用的操作.

在 stream 的发送部分, 应用协议可以:

  • 写入数据, 并了解何时已成功预留 stream flow control credit (第 4.1 节) 以发送写入的数据;

  • 结束 stream (clean termination), 从而产生一个 FIN bit 被设置的 STREAM frame (第 19.8 节); 以及

  • 重置 stream (abrupt termination), 如果 stream 尚未处于 terminal state, 则产生一个 RESET_STREAM frame (第 19.4 节).

在 stream 的接收部分, 应用协议可以:

  • 读取数据; 以及

  • 中止读取该 stream 并请求关闭, 这可能产生一个 STOP_SENDING frame (第 19.5 节).

应用协议还可以请求获知 stream 上的状态变化, 包括 peer 何时打开或重置 stream, peer 何时中止读取某个 stream, 新数据何时可用, 以及由于 flow control 何时能够或不能向该 stream 写入数据.