メインコンテンツまでスキップ

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 │
└─────────┘ └─────────┘

ストリームのライフサイクル

作成 → データ送信 → 終了/リセット → クローズ
↑ ↓
└─ フロー制御 ←┘

主要特性

  1. 軽量: 単一のフレームでストリームを開き、転送し、閉じることができる
  2. 並行性: 任意の数のストリームが同時にアクティブになれる
  3. 独立性: ストリーム間で順序を保証せず、ヘッドオブラインブロッキングを回避
  4. 柔軟性: 長期間存在することも短期間使用することもできる

TCPとの比較

特性QUICストリームTCP
多重化✅ ネイティブマルチストリームサポート❌ 単一バイトストリーム
ヘッドオブラインブロッキング✅ ストリームレベルで独立❌ グローバルブロッキング
ストリーム作成オーバーヘッド極めて低いN/A
優先順位制御アプリケーション層が決定なし

次の章: 3. Stream States (ストリーム状態) - 詳細なストリーム状態マシンモデル