LPWSPDUPLICATESOCKET
コールバックシグネチャ
INT LPWSPDUPLICATESOCKET(
SOCKET s,
DWORD dwProcessId,
WSAPROTOCOL_INFOW* lpProtocolInfo,
INT* lpErrno
);パラメーター
| フィールド | 型 | 説明 |
|---|---|---|
| s | SOCKET | ローカルのソケット記述子。 |
| dwProcessId | DWORD | 共有ソケットを使用する対象プロセスの識別子。 |
| lpProtocolInfo | WSAPROTOCOL_INFOW* | WSAPROTOCOL_INFO 構造体を格納できる十分な大きさの、クライアントが割り当てたバッファーへのポインター。サービスプロバイダーは、プロトコル情報構造体の内容をこのバッファーにコピーします。 |
| lpErrno | INT* | エラーコードへのポインター。 |
公式ドキュメント
LPWSPDuplicateSocket 関数は、共有ソケット用の新しいソケット記述子の作成に使用できる WSAPROTOCOL_INFO 構造体を返します。
戻り値
エラーが発生しなかった場合、LPWSPDuplicateSocket はゼロを返します。それ以外の場合は SOCKET_ERROR が返され、具体的なエラー番号を lpErrno で取得できます。
| エラーコード | 意味 |
|---|---|
| ネットワークサブシステムに障害が発生しました。 | |
| 指定されたパラメーターのいずれかが無効であることを示します。 | |
| ブロッキング Windows Sockets 呼び出しが進行中であるか、サービスプロバイダーがコールバック関数の処理中です。 | |
| 使用可能なソケット記述子がこれ以上ありません。 | |
| 使用可能なバッファー領域がありません。ソケットを作成できません。 | |
| 記述子がソケットではありません。 |
解説(Remarks)
ソースプロセスは、特別な WSAPROTOCOL_INFO 構造体を取得するために LPWSPDuplicateSocket を呼び出します。ソースプロセスは何らかのプロセス間通信 (IPC) メカニズムを使用してこの構造体の内容を対象プロセスに渡し、対象プロセスはそれを LPWSPSocket の呼び出しで使用して、複製されたソケットの記述子を取得します。この特別な WSAPROTOCOL_INFO 構造体は、対象プロセスで一度しか使用できないことに注意してください。
ソースプロセスのコンテキストで必要な操作をすべて実行し、その後に対象プロセスのコンテキストで LPWSPSocket のパラメーターとして渡されたときに認識される WSAPROTOCOL_INFO 構造体を作成することは、サービスプロバイダーの責任です。プロバイダーはその後、共通の基になるソケットを参照するソケット記述子を返す必要があります。WSAPROTOCOL_INFO 構造体の dwProviderReserved メンバーはサービスプロバイダーが自由に使用でき、複製されたハンドルなど、任意の有用なコンテキスト情報の格納に利用できます。
新しいソケット記述子が割り当てられるとき、インストール可能ファイルシステム (IFS) プロバイダーは WPUModifyIFSHandle を呼び出す必要があり、非 IFS プロバイダーは WPUCreateSocketHandle を呼び出す必要があります。IFS プロバイダーは DuplicateHandle 関数を使用できます。ソケットの複製を正しく実行するために、非 IFS サービスプロバイダーは LPWSPDuplicateSocket 関数を使用する必要があります。
ハンドオフモードで共有ソケットを確立して使用する場合のシナリオの一例を次に示します。
| ソースプロセス | IPC | Meaning |
|---|---|---|
|
==> | |
|
|
3) プロセス識別子の要求を受け取り、応答します。 | |
|
<== | |
|
||
|
||
|
|
==> | 7) WSAPROTOCOL_INFO 構造体を受け取ります。 |
|
|
8) LPWSPSocket を呼び出して、共有ソケット記述子を作成します。 | |
|
|
9) 共有ソケットを使用してデータを交換します。 | |
|
<== |
共有ソケットを参照する記述子は、I/O に関する限り、それぞれ独立して使用できます。ただし、Windows Sockets インターフェイスはいかなる種類のアクセス制御も実装していないため、共有ソケットに対する操作の調整は、関係するプロセスに委ねられます。共有ソケットの典型的な用途は、ソケットの作成と接続の確立を担当する 1 つのプロセスが、情報交換を担当する他のプロセスにソケットを引き渡すというものです。
複製されるのはソケット記述子であって基になるソケットではないため、ソケットに関連付けられたすべての状態は、すべての記述子で共通に保持されます。たとえば、ある記述子を使用して実行した WSPSetSockOpt 操作は、その後いずれの記述子からの LPWSPGetSockopt でも参照できます。プロセスは複製されたソケットに対して LPWSPCloseSocket を呼び出すことができ、その記述子は解放されます。ただし、基になるソケットは、最後に残った記述子から LPWSPClosesocket が呼び出されるまで開いたままになります。
共有ソケットでの通知は、LPWSPAsyncSelect および LPWSPEventSelect の通常の制約を受けます。共有された記述子のいずれかを使用してこれらの呼び出しのどちらかを発行すると、どの記述子で登録が行われたかにかかわらず、そのソケットに対する以前のイベント登録は取り消されます。したがって、たとえば共有ソケットが FD_READ イベントをプロセス A に、FD_WRITE イベントをプロセス B に配信することはできません。そのような緊密な連携が必要な場合は、別々のプロセスではなくスレッドを使用することをお勧めします。
階層化サービスプロバイダーはこの関数の実装を提供しますが、プロトコルチェーン内の次の階層の LPWSPDuplicateSocket を呼び出す場合には、この関数のクライアントでもあります。この関数の lpProtocolInfo パラメーターについては、プロトコルチェーンの各階層を下方向に伝播する際に特別な考慮事項が適用されます。
プロトコルチェーン内の次の階層がさらに別の階層である場合、次の階層の LPWSPDuplicateSocket を呼び出すときに、この階層は、変更されていない同じチェーン情報を持つ、変更されていない同じ WSAPROTOCOL_INFO 構造体を参照する lpProtocolInfo を次の階層に渡す必要があります。ただし、次の階層がベースプロトコル (つまりチェーンの最後の要素) である場合、この階層はベースプロバイダーの LPWSPDuplicateSocket を呼び出す際に置き換えを行います。この場合、lpProtocolInfo パラメーターはベースプロバイダーの WSAPROTOCOL_INFO 構造体を参照する必要があります。
この方針の重要な利点の 1 つは、ベースサービスプロバイダーがプロトコルチェーンを意識する必要がないことです。同じ方針は、LPWSPAddressToString、WSPStartup、LPWSPSocket、LPWSPStringToAddress などの他の関数の階層化されたシーケンスを通じて WSAPROTOCOL_INFO 構造体を伝播する場合にも適用されます。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)