欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

透彻解析QUIC协议(第二部分):详解QUIC中的数据流机制

最编程 2024-07-31 15:40:21
...

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

一、QUIC流的特性

Streams in QUIC provide a lightweight, ordered byte-stream abstraction to an application.

QUIC中的流为应用程序提供了一个轻量级的,有序的字节流抽象。

QUIC流有以下几种特性:

  1. 有序

应用层在使用QUIC流时,不需要考虑数据的乱序问题,QUIC在协议层为我们提供了这种保障。

  1. 支持单向、双向

QUIC支持创建单向流或双向流,单向流只允许发送端发送数据,双向流允许双端发送数据。

  1. 流创建不限制数量

在同一个连接上可以创建任意数量的流,满足多路复用的需求。

  1. 在流上发送数据无限制

在每路流上发送的数据量是没有限制的,可大可小,例如你可以使用一路流仅仅每分钟发送一次心跳,而在另一路流上发送每秒几Mb的视频数据。

二、QUIC流的细节

stream ID与流类型的关系

流ID的形式是62位整形数字,生成流ID时要保障该流ID在连接内是唯一的,并且打开一个新流时是不能复用已关闭的流ID的。

流ID的最低两位与流的类型有关:

最低位标识了流的发起方,值为0表示该流由客户端发起,值为1表示该流由服务端发起。

倒数第二位标识流的方向,值为0表示这是一条双向流,值为1表示该流是单向流。

image.png

最低有效位 第二低有效位 发起方 流方向
0 0 0x0 客户端 双向
1 0 0x1 服务端 双向
0 1 0x2 客户端 单向
1 1 0x3 服务端 单向

数据的收发

应用数据被封装在流桢内发送,在同一路流内使用offset确定数据的顺序。接收端的实现会缓存乱序的数据以在将数据排序后交给上层。

发送端在同一路流上不允许使用相同的offset发送不同的数据,如果发送端这样做了,接收端会抛出一个PROTOCOL_VIOLATION的连接异常。

发送端在未确认发送的数据是否在对端流控允许范围内时,也不允许发送数据。

优先级

可以在应用层指定流的相对优先级。

在某些应用场景下区分流的优先级是很有用的:

例如两路流分别传输音频、视频数据,人对声音卡顿的敏感度是要高于视频的,这种情况下一般都会优先保障音频的传输,在网络状况不好的情况下允许一定程度的视频卡顿。此时将音频数据流的优先级设置的更高,就能较容易的实现这点。

流支持的操作

对QUIC流可以进行以下几类操作:

发送端操作

  1. 发送端可以依照流控的指示向流写数据。

  2. 可以重置流。

  3. 可以终止流。

关于重置流和终止流的具体含义和细节将在后面讨论。

接收端操作

  1. 读数据。

  2. 可以终止读数据(同时通知发送端)。

注册回调

在实际使用QUIC协议栈时,应用程序很多情况下会关心流的状态,QUIC提供了以下几类可注册的回调:

  1. 流打开、关闭的状态转换。

  2. 对方中止了读。

  3. 有数据可读。

  4. 流可写、流不可写的状态转换。

三、本篇总结

  1. QUIC流在协议层保障了数据有序,应用层在使用QUIC流时无需关注乱序问题。

  2. 流有单双向之分,使用时可以按需创建(使用单向流在某些实现上或许能够节约一些资源)。

  3. 创建流的数量、在各路流上发送的数据量都是无限制的,能很好的满足多路复用需求。

  4. Stream ID的最低两个有效位标识了流的发起方与方向。

  5. 可以根据应用场景的需要设置流的优先级,在网络条件差时,优先级高的流会被更好的传输。

  6. 发送端、接收端对流可以进行不同的操作(当然一个终端可以即是发送端又是接收端),使用QUIC api时可以注册一些回调关注流的状态,例如流的打开、关闭、可读、可写、被中止等。