2. Streams (ストリーム)
QUICのストリームは、アプリケーションに軽量で順序付けられたバイトストリーム抽象 (Ordered Byte-Stream Abstraction) を提供します。ストリームは単方向 (Unidirectional) または双方向 (Bidirectional) にすることができます。
ストリームはデータを送信することで作成できます。ストリーム管理に関連する他のプロセス(終了、キャンセル、フロー制御の管理)は、すべて最小限のオーバーヘッドを課すように設計されています。たとえば、単一のSTREAMフレーム(第19.8節)でストリームを開き、データを運び、ストリームを閉じることができます。ストリームは長期間存在することもでき、接続の全期間にわたって継続できます。
ストリームはどちらのエンドポイントでも作成でき、他のストリームとインターリーブして同時にデータを送信でき、キャンセルできます。QUICは、異なるストリーム上のバイト間の順序を保証する手段を提供しません。
QUICは、フロー制御の制約とストリーム制限に従って、任意の数のストリームを同時に動作させ、任意の量のデータを任意のストリームで送信することを許可します。第4節を参照してください。
2.1. Stream Types and Identifiers (ストリームタイプと識別子)
ストリームは単方向または双方向にすることができます。単方向ストリームは一方向にデータを運びます:ストリームの開始者からそのピアへ。双方向ストリームは両方向にデータを送信することを許可します。
ストリームは接続内で数値によって識別され、ストリームID (Stream ID) と呼ばれます。ストリームIDは62ビット整数(0から2^62-1)であり、接続上のすべてのストリームに対して一意です。ストリームIDは可変長整数としてエンコードされます。第16節を参照してください。QUICエンドポイントは接続内でストリームIDを再利用してはなりません (MUST NOT)。
ストリームIDエンコーディングルール
ストリームIDの最下位ビット (0x01) はストリームの開始者を識別します:
- クライアント開始ストリーム: ストリームIDは偶数(ビットが0に設定)
- サーバー開始ストリーム: ストリームIDは奇数(ビットが1に設定)
ストリームIDの2番目の最下位ビット (0x02) は以下を区別します:
- 双方向ストリーム: ビットが0に設定
- 単方向ストリーム: ビットが1に設定
ストリームタイプテーブル
したがって、ストリームIDの2つの最下位ビットは、ストリームを4つのタイプのいずれかとして識別します。表1にまとめられています:
| ビット値 | ストリームタイプ |
|---|---|
| 0x00 | クライアント開始、双方向 (Client-Initiated, Bidirectional) |
| 0x01 | サーバー開始、双方向 (Server-Initiated, Bidirectional) |
| 0x02 | クライアント開始、単方向 (Client-Initiated, Unidirectional) |
| 0x03 | サーバー開始、単方向 (Server-Initiated, Unidirectional) |
表1: ストリームIDタイプ
ストリームID割り当てルール
各タイプのストリームスペースは最小値から始まります(それぞれ0x00から0x03)。各タイプの後続のストリームは、数値的に増加するストリームIDで作成されます。順序外で使用されるストリームIDは、そのタイプの低い番号のストリームIDを持つすべてのストリームも開かれることになります。
2.2. Sending and Receiving Data (データの送受信)
STREAMフレーム(第19.8節)は、アプリケーションによって送信されたデータをカプセル化します。エンドポイントは、STREAMフレーム内のストリームID (Stream ID) とオフセット (Offset) フィールドを使用してデータを順序付けます。
エンドポイントは、ストリームデータを順序付けられたバイトストリームとしてアプリケーションに配信できなければなりません (MUST)。順序付けられたバイトストリームを配信するには、エンドポイントが、通知されたフロー制御制限まで、順序外で受信されたデータをバッファリングする必要があります。
データ配信オプション
QUICは、ストリームデータを順序外で配信するための特定の規定を行いません。ただし、実装は、データを順序外で受信アプリケーションに配信する機能を提供することを選択できます (MAY)。
データの重複と一貫性
エンドポイントは、同じストリームオフセットでストリームのデータを複数回受信する可能性があります。すでに受信されたデータは破棄できます。複数回送信される場合、特定のオフセットのデータは変更してはなりません (MUST NOT)。エンドポイントは、ストリーム内の同じオフセットで異なるデータを受信することを、タイプPROTOCOL_VIOLATIONの接続エラーとして扱うことができます (MAY)。
フレーム境界
ストリームは順序付けられたバイトストリーム抽象であり、QUICには他の可視構造はありません。データが送信、パケット損失後に再送信、または受信側でアプリケーションに配信されるときに、STREAMフレーム境界が保持されることは期待されていません。
フロー制御
エンドポイントは、ピアによって設定されたフロー制御制限内であることを確認せずに、任意のストリームでデータを送信してはなりません (MUST NOT)。フロー制御は第4節で詳しく説明されています。
2.3. Stream Prioritization (ストリーム優先順位付け)
ストリームに割り当てられたリソースが正しく優先順位付けされている場合、ストリーム多重化はアプリケーションパフォーマンスに大きな影響を与える可能性があります。
QUICは優先順位情報を交換するメカニズムを提供しません。代わりに、アプリケーションから優先順位情報を受け取ることに依存しています。
QUIC実装は、アプリケーションがストリームの相対的な優先順位を示すことができる方法を提供すべきです (SHOULD)。実装は、アプリケーションによって提供された情報を使用して、アクティブなストリームにリソースを割り当てる方法を決定します。
優先順位メカニズムの説明
HTTP/2との違い:
- HTTP/2はプロトコルレイヤーで優先順位ツリー (Priority Tree) を定義
- QUICは優先順位決定をアプリケーション層に委ねる
- これにより柔軟性が向上しますが、アプリケーションプロトコルが独自の優先順位スキームを設計する必要があります
2.4. Operations on Streams (ストリームでの操作)
この文書はQUICのAPIを定義していません。代わりに、アプリケーションプロトコルが依存できるストリーム上の一連の関数を定義します。アプリケーションプロトコルは、QUIC実装が本節で説明されている操作を含むインターフェースを提供すると仮定できます。特定のアプリケーションプロトコルで使用するために設計された実装は、そのプロトコルで使用される操作のみを提供する場合があります。
送信側操作
ストリームの送信側では、アプリケーションプロトコルは次のことができます:
データの書き込み (Write Data)
書き込まれたデータを送信するためにストリームフロー制御クレジット(第4.1節)がいつ正常に予約されたかを理解する
ストリームの終了 (End Stream) - クリーンな終了
FINビットが設定されたSTREAMフレーム(第19.8節)の送信につながる
ストリームのリセット (Reset Stream) - 突然の終了
ストリームがまだ終端状態にない場合、RESET_STREAMフレーム(第19.4節)の送信につながる
受信側操作
ストリームの受信側では、アプリケーションプロトコルは次のことができます:
データの読み取り (Read Data)
ストリームから受信したデータを読み取る
読み取りの中止 (Abort Reading)
ストリームの読み取りを中止してクローズを要求し、STOP_SENDINGフレーム(第19.5節)の送信につながる可能性がある
状態通知
アプリケーションプロトコルは、以下を含むストリームの状態変化について通知を受けることも要求できます:
- ピアがストリームを開いたかリセットしたとき
- ピアがストリームでの読み取りを中止したとき
- 新しいデータが利用可能になったとき
- フロー制御のためにストリームにデータを書き込むことができるかできないかとき
💡 ストリームメカニズムの核心ポイント
4種類のストリーム
クライアント開始 サーバー開始
↓ ↓
┌─────────┐ ┌─────────┐
│ 双方向 │ (ID: 0,4,8..)│ 双方向 │ (ID: 1,5,9..)
│ 0x00 │ │ 0x01 │
└─────────┘ └─────────┘
┌─────────┐ ┌─────────┐
│ 単方向 │ (ID: 2,6,10..)│ 単方向 │ (ID: 3,7,11..)
│ 0x02 │ │ 0x03 │
└─────────┘ └─────────┘
ストリームのライフサイクル
作成 → データ送信 → 終了/リセット → クローズ
↑ ↓
└─ フロー制御 ←┘
主要特性
- 軽量: 単一のフレームでストリームを開き、転送し、閉じることができる
- 並行性: 任意の数のストリームが同時にアクティブになれる
- 独立性: ストリーム間で順序を保証せず、ヘッドオブラインブロッキングを回避
- 柔軟性: 長期間存在することも短期間使用することもできる
TCPとの比較
| 特性 | QUICストリーム | TCP |
|---|---|---|
| 多重化 | ✅ ネイティブマルチストリームサポート | ❌ 単一バイトストリーム |
| ヘッドオブラインブロッキング | ✅ ストリームレベルで独立 | ❌ グローバルブロッキング |
| ストリーム作成オーバーヘッド | 極めて低い | N/A |
| 優先順位制御 | アプリケーション層が決定 | なし |
次の章: 3. Stream States (ストリーム状態) - 詳細なストリーム状態マシンモデル