2.Stream
QUIC 中的流为应用程序提供了轻量级、有序的字节流抽象。 流可以是单向的或双向的。
可以通过发送数据来创建流。 与流管理相关的其他过程——结束、取消和管理流控制——都旨在施加最小的开销。 例如,单个 STREAM 帧(第 19.8 节)可以打开、携带和关闭流的数据。 流也可以是长期存在的,并且可以持续整个连接期间。
流可以由任一端点创建,可以同时发送与其他流交错的数据,并且可以取消。 QUIC 不提供任何方法来确保不同流上的字节之间的排序。
QUIC 允许任意数量的流同时运行,并允许在任何流上发送任意数量的数据,受流控制约束和流限制; 见第 4 节
2.1 流类型和标识符
流可以是单向的或双向的。 单向流在一个方向上传输数据:从流的发起者到其对等方。 双向流允许双向发送数据。
流在连接中由一个数值标识,称为流 ID。 流 ID 是一个 62 位整数(0 到 262-1),对于连接上的所有流都是唯一的。 流 ID 被编码为变长整数; 请参阅第 16 节。QUIC 端点不得在连接中重用流 ID。
流 ID 的最低有效bit位 (0x01) 标识流的发起者。 客户端启动的流具有偶数的流 ID(bit位设置为 0),服务器启动的流具有奇数的流 ID(bit位设置为 1)。
流 ID 的第二个最低有效bit位 (0x02) 区分双向流(位设置为 0)和单向流(位设置为 1)。
因此,流 ID 中的两个最低有效位将流标识为四种类型之一,如表 1 所示
Bits | Stream Type |
---|---|
0x00 | Client-Intiated,Bidirectional |
0x01 | Server-Intiated,Bidirectional |
0x02 | Client-Intiated,Unidirectional |
0x03 | Server-Intiated,Unidirectional |
Table1:Stream ID Types |
每种类型的流空间从最小值开始(分别为 0x00 到 0x03); 每种类型的连续流都是使用数字递增的流 ID 创建的。 乱序使用的流 ID 会导致所有具有较低编号流 ID 的类型的流也被开启。
2.2 发送和接受数据包
STREAM 帧(第 19.8 节)封装了应用程序发送的数据。 端点使用 STREAM 帧中的 Stream ID 和 Offset 字段来按顺序放置数据。
端点必须能够将流数据作为有序字节流传递给应用程序。 交付有序字节流需要端点缓冲任何乱序接收的数据,直至广播流量控制限制。
QUIC 没有特别考虑流数据的乱序传输。 然而,实现可以选择提供将乱序数据传送到应用程序的能力。
端点可以多次接收同一流偏移处(Offset)的流的数据。 已经接收到的数据可以被丢弃。 如果多次发送,给定偏移量处的数据会发生变化; 端点将流中以相同偏移量接收到不同数据视为 PROTOCOL_VIOLATION 类型的连接错误。
流是一种有序的字节流抽象,QUIC 看不到其他结构。 STREAM 帧边界在数据传输、丢包后重传或在接收者处传递给应用程序时不会被保留。
端点不得在任何流上发送数据,除非确保它在其对等方设置的流量控制限制内。 流量控制在第 4 节中详细描述
2.3 流的优先级
如果分配给流的资源得到正确的优先级,则流多路复用会对应用程序性能产生重大影响。
QUIC 不提供交换优先级信息的机制。 相反,它依赖于从应用程序接收优先级信息。
一个QUIC协议的实现,应该提供给应用指定流优先级的方法。 以此实现按照应用程序提供的信息,来确定如何将资源分配给active stream(这里是因为翻译的不地道,大家自己理解一下)
2.4 对流的操作
本文档没有为 QUIC 定义 API; 相反,它在应用程序协议可以依赖的流上定义了一组函数。 应用程序协议可以假设 QUIC 实现提供了一个接口,该接口包含本节中描述的操作。 设计用于特定应用程序协议的实现可能仅提供该协议使用的那些操作。
在流的发送部分,应用协议可以:
- 写入数据时,了解何时成功保留流量控制凭证(credit)(第 4.1 节)以发送写入的数据;
- 结束流(干净终止),产生一个设置了 FIN bit位的 STREAM 帧(第 19.8 节);
- 并重置流(突然终止),如果流尚未处于终止状态,则导致 RESET_STREAM 帧(第 19.4 节)。
在流的接收部分,应用协议可以:
-
读取数据;
-
中止读取流并请求关闭,可能导致 STOP_SENDING 帧(第 19.5 节)。
应用程序协议还可以请求,当流的状态发生变化的时候来通知,包括对等方何时打开或重置流、何时中止对流的读取、何时有新数据可用以及当被流量控制的时候,可不可以写入数据。