Share via


帯域外データのProtocol-Independent

ストリーム ソケットの抽象化には、帯域外 (OOB) データの概念が含まれます。 多くのプロトコルでは、受信データの一部を何らかの方法で特殊としてマークすることができ、これらの特殊なデータ ブロックは通常のシーケンスからユーザーに配信できます。 例としては、X.25 やその他の OSI プロトコルの優先データや、BSD UNIX による TCP の使用における緊急データなどがあります。 次のセクションでは、プロトコルに依存しない方法での OOB データ処理について説明します。 TCP 緊急データを使用して実装された OOB データについては、プロトコルに依存しない説明に従います。 各説明では、 recv の使用も recvfromWSARecv、および WSARecvFrom を意味し、 WSAAsyncSelect への参照は WSAEventSelect にも適用されます。

プロトコルに依存しない OOB データ

OOB データは、接続されたストリーム ソケットの各ペアに関連付けられている論理的に独立した伝送チャネルです。 OOB データは、通常のデータとは無関係にユーザーに配信できます。 抽象化では、OOB データ機能が、少なくとも 1 つの OOB データ ブロックの信頼性の高い配信を一度にサポートする必要があることを定義します。 このデータ ブロックには、少なくとも 1 バイトのデータを含めることができます。また、少なくとも 1 つの OOB データ ブロックを、ユーザーへの一度に配信待ちにすることができます。 インバンドシグナリングをサポートする通信プロトコル (通常のデータと順番に緊急データが配信される TCP など) の場合、システムは通常、通常のデータ ストリームから OOB データを抽出し、個別に格納します (通常のデータ ストリームにギャップを残します)。 これにより、ユーザーは、OOB データを順番に受信し、すべてのデータをバッファーに格納せずに順に受信することを選択できます。 帯域外 (OOB) データをピークできます。

ユーザーは、 IOCTLSocket 関数または WSAIoctl 関数と SIOCATMARK IOCTL を使用して、OOB データの読み取りを待機しているかどうかを判断できます。 通常のデータ ストリーム内での OOB データ ブロックの位置の概念が意味のあるプロトコル (TCP など) の場合、Windows ソケット サービス プロバイダーは、通常のデータ ストリーム内の OOB データの最後のバイトの位置を示す概念マーカーを保持します。 これは、SIOCATMARK をサポートする ioctlsocket または WSAIoctl 関数の実装には必要ありません。 OOB データの有無がすべて必要です。

通常のデータ ストリーム内での OOB データ ブロックの位置の概念が意味のあるプロトコルの場合、アプリケーションは通常のデータ ストリームの一部として帯域外データをインラインで処理する場合があります。 これは、 setsockopt 関数を使用してソケット オプションSO_OOBINLINEを設定することで実現されます。 OOB データ ブロックが通常のデータ ストリームに完全に依存しない他のプロトコルでは、SO_OOBINLINEを設定しようとするとエラーが発生します。 アプリケーションは、 ioctlsocket または WSAIoctl 関数を SIOCATMARK IOCTL と共に使用して、マークの前に未読の OOB データがあるかどうかを判断できます。 たとえば、この情報を使用して、必要に応じてデータ ストリーム内のマークまでのすべてのデータが破棄されるようにすることで、ピアと再同期できます。

SO_OOBINLINE無効 (既定の設定) の場合:

  • Windows ソケットは、アプリケーションが WSAAsyncSelect に通知するために登録されている場合、通常のデータの存在を通知するためにFD_READが使用されるのとまったく同じ方法で、FD_OOB イベントをアプリケーションに通知します。 つまり、FD_OOBは、OOB データが以前にキューに登録されていない状態で OOB データが到着したときにポストされます。 FD_OOBは、読み取り操作が返された後も一部の OOB データがキューに残っている間に、MSG_OOB フラグを使用してデータを読み取るときにも投稿されます。 FD_READメッセージは OOB データに対して投稿されません。
  • OOB データがソケットでキューに入れている場合、Windows ソケットは select から適切な exceptfds ソケット セットを返します。
  • アプリケーションは、緊急のデータ ブロックをいつでも読み取るために、MSG_OOBを使用して recv を呼び出すことができます。 OOB データのブロックがキューにジャンプします。
  • アプリケーションは、通常のデータ ストリームを読み取るために、MSG_OOBなしで recv を呼び出すことができます。 OOB データ ブロックは、通常のデータを含むデータ ストリームには表示されません。 recv の呼び出し後に OOB データが残っている場合、Windows ソケットは select を使用するときに、FD_OOBまたは exceptfds を使用してアプリケーションに通知します
  • OOB データが通常のデータ ストリーム内の位置を持つプロトコルの場合、1 つの recv 操作がその位置にまたがることはありません。 1 つの recv はマークの前に通常のデータを返し、マークの後にデータの読み取りを開始するには 2 番目の recv が必要です。

SO_OOBINLINEが有効になっている場合:

  • FD_OOBメッセージは OOB データに対して投稿されません。 OOB データは 、select 関数と WSAAsyncSelect 関数の目的で通常と見なされ、 readfds でソケットを設定するか、FD_READ メッセージをそれぞれ送信することによって示されます。
  • アプリケーションは、OOB データ ブロックを読み取るために MSG_OOB フラグを設定して recv を呼び出すことはできません。 エラー コード WSAEINVAL が返されます。
  • アプリケーションは、MSG_OOB フラグを設定せずに recv を呼び出すことができます。 OOB データは、通常のデータ ストリーム内で正しい順序で配信されます。 OOB データが通常のデータと混在することはありません。 OOB データを取得するには、3 つの読み取り要求が必要です。 1 つ目は OOB データ ブロックより前の通常のデータを返し、2 つ目は OOB データを返し、3 つ目は OOB データの後に通常のデータを返します。 つまり、OOB データ ブロックの境界は保持されます。

WSAAsyncSelect ルーチンは、SO_OOBINLINEがオフのときに帯域外データの存在の通知を処理するのに特に適しています。

TCP の OOB データ

重要

TCP 緊急データを使用して実装された帯域外データ (OOB) の次の説明は、バークレイソフトウェアディストリビューションで使用されるモデルに従います。 ユーザーと実装者は、次の点に注意する必要があります。

 

  • 現時点では、 RFC 793 の 2 つの競合する解釈があります (この概念が導入されています)。

  • Rfc 1122 で指定されているホスト要件に適合しない OOB データを、バークレイ ソフトウェアディストリビューション (BSD) に実装します。

    具体的には、BSD の TCP 緊急ポインターは緊急データ バイトの後のバイトを指し、RFC 準拠の TCP 緊急ポインターは緊急データ バイトを指します。 その結果、アプリケーションが BSD 互換の実装から RFC 1122 と互換性のある実装に緊急データを送信すると、受信側は間違った緊急データ バイトを読み取ります (データ ストリーム内の正しいバイトの後にあるバイトを緊急データ バイトとして読み取ります)。

    相互運用性の問題を最小限に抑えるために、アプリケーション ライターは、既存のサービスとの相互運用に必要な場合を除き、OOB データを使用しないことをお勧めします。 Windows ソケット サプライヤーは、製品が実装する OOB セマンティクス (BSD または RFC 1122) を文書化するよう求められます。

URG (緊急用) フラグが設定された TCP セグメントの到着は、TCP データ ストリーム内に 1 バイトの OOB データが存在することを示します。 OOB データ ブロックのサイズは 1 バイトです。 緊急ポインターは、TCP ヘッダー内の現在のシーケンス番号からの正のオフセットです。これは、OOB データ ブロックの場所を示します (前述のようにあいまいです)。 したがって、まだ受信されていないデータを指している可能性があります。

緊急ポインターが指すバイトを含む TCP セグメントが到着したときにSO_OOBINLINEが無効になっている場合 (既定値)、OOB データ ブロック (1 バイト) がデータ ストリームから削除され、バッファー処理されます。 緊急フラグが設定された後続の TCP セグメント (および新しい緊急ポインター) が到着した場合、現在キューに入っている OOB バイトは、新しい OOB データ ブロックに置き換えられると失われる可能性があります (これは、バークレイソフトウェア配布で発生します)。 ただし、データ ストリームでは置き換えされません。

SO_OOBINLINE有効にすると、緊急データはデータ ストリームに残ります。 その結果、緊急データを含む新しい TCP セグメントが到着しても、OOB データ ブロックは失われることはありません。 既存の OOB データ マークが新しい位置に更新されます。

Note

SO_OOBINLINE ソケット オプションを設定すると、SIOCATMARK IOCTL は常に TRUE を返し、OOB データは通常のデータとしてユーザーに返されます。