Win32 API 日本語リファレンス
ホーム › Networking.WinSock › LPWSPRECV

LPWSPRECV

コールバック

シグネチャ

INT LPWSPRECV(
    SOCKET s,
    WSABUF* lpBuffers,
    DWORD dwBufferCount,
    DWORD* lpNumberOfBytesRecvd,
    DWORD* lpFlags,
    OVERLAPPED* lpOverlapped,
    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
    WSATHREADID* lpThreadId,
    INT* lpErrno
);

パラメーター

フィールド型説明
sSOCKET接続済みソケットを識別する記述子です。
lpBuffersWSABUF*WSABUF 構造体の配列へのポインターです。各 WSABUF 構造体には、バッファーへのポインターと、そのバッファーの長さ (バイト単位) が格納されます。
dwBufferCountDWORDlpBuffers 配列内の WSABUF 構造体の数です。
lpNumberOfBytesRecvdDWORD*この呼び出しで受信したバイト数へのポインターです。
lpFlagsDWORD*呼び出しの方法を指定するフラグへのポインターです。
lpOverlappedOVERLAPPED*WSAOverlapped 構造体へのポインターです (非オーバーラップ構造体の場合は無視されます)。
lpCompletionRoutineLPWSAOVERLAPPED_COMPLETION_ROUTINE受信操作が完了したときに呼び出される完了ルーチンへのポインターです (非オーバーラップ構造体の場合は無視されます)。
lpThreadIdWSATHREADID*WSATHREADID 構造体へのポインターで、プロバイダーが後続の WPUQueueApc の呼び出しで使用します。プロバイダーは、WPUQueueApc 関数が戻るまで、参照先の WSATHREADID 構造体 (そのポインターではなく構造体そのもの) を保持する必要があります。
lpErrnoINT*エラーコードへのポインターです。

公式ドキュメント

LPWSPRecv 関数は、ソケット上でデータを受信します。

戻り値

エラーが発生せず、受信操作がただちに完了した場合、LPWSPRecv は 0 を返します。この場合、完了ルーチンが指定されていれば、すでにキューに登録されている点に注意してください。それ以外の場合は SOCKET_ERROR が返され、具体的なエラーコードは lpErrno で取得できます。エラーコード WSA_IO_PENDING は、オーバーラップ操作が正常に開始され、完了が後で通知されることを示します。それ以外のエラーコードは、オーバーラップ操作が開始されておらず、完了通知も発生しないことを示します。

エラーコード 意味
WSAENETDOWN
ネットワークサブシステムに障害が発生しました。
WSAENOTCONN
ソケットが接続されていません。
WSAEINTR
(ブロッキング) 呼び出しが LPWSPCancelBlockingCall によってキャンセルされました。
WSAEINPROGRESS
ブロッキング Windows ソケット呼び出しが進行中であるか、サービスプロバイダーがまだコールバック関数を処理しています。
WSAENETRESET
操作の進行中に keep-alive の動作が障害を検出したため、接続が切断されました。
WSAEFAULT
lpBuffers パラメーターの全体が、ユーザーアドレス空間の有効な部分に収まっていません。
WSAENOTSOCK
記述子がソケットではありません。
WSAEOPNOTSUPP
MSG_OOB が指定されましたが、ソケットが SOCK_STREAM 型などのストリーム型ではないか、このソケットに関連付けられた通信ドメインで OOB データがサポートされていないか、ソケットが単方向で送信操作のみをサポートしています。
WSAESHUTDOWN
ソケットがシャットダウンされています。how に SD_RECEIVE または SD_BOTH を指定して LPWSPShutdown を呼び出した後は、そのソケットで LPWSPRecv による受信はできません。
WSAEWOULDBLOCK
Windows NT:  オーバーラップソケット: 未処理のオーバーラップ I/O 要求が多すぎます。非オーバーラップソケット: ソケットが非ブロッキングとしてマークされており、受信操作をただちに完了できません。
WSAEMSGSIZE
メッセージが大きすぎて指定されたバッファーに収まらず、(信頼性のないプロトコルの場合のみ) バッファーに収まらなかったメッセージの末尾部分は破棄されました。
WSAEINVAL
ソケットが (たとえば LPWSPBind によって) バインドされていないか、ソケットがオーバーラップフラグ付きで作成されていません。
WSAECONNABORTED
タイムアウトまたはその他の障害により、仮想回線が終了しました。
WSAECONNRESET
仮想回線がリモート側によってリセットされました。
WSAEDISCON
ソケット s はメッセージ指向であり、仮想回線がリモート側によって正常にクローズされました。
WSA_IO_PENDING
オーバーラップ操作が正常に開始され、完了は後で通知されます。
WSA_OPERATION_ABORTED
ソケットがクローズされたため、オーバーラップ操作がキャンセルされました。

解説(Remarks)

LPWSPRecv は、s パラメーターで指定された接続済みソケットまたはバインド済みのコネクションレスソケットで使用し、受信データを読み取ります。ソケットのローカルアドレスが判明している必要があります。これは LPWSPBind によって明示的に行うか、LPWSPAccept、LPWSPConnect、LPWSPSendTo、LPWSPJoinLeaf によって暗黙的に行います。

接続されたコネクションレスソケットの場合、この関数は受信メッセージを受け入れるアドレスを制限します。この関数は、接続で指定されたリモートアドレスからのメッセージのみを返します。他のアドレスからのメッセージは (通知なく) 破棄されます。

オーバーラップソケットの場合、LPWSPRecv は 1 つ以上のバッファーをポストするために使用され、受信データは利用可能になった時点でそれらのバッファーに格納されます。その後、Windows ソケット SPI クライアントが指定した完了通知 (完了ルーチンの呼び出し、またはイベントオブジェクトのシグナル設定) が行われます。操作がただちに完了しない場合、最終的な完了状態は完了ルーチンまたは LPWSPGetOverlappedResult を通じて取得します。

lpOverlapped と lpCompletionRoutine の両方が null の場合、この関数ではソケットは非オーバーラップソケットとして扱われます。

非オーバーラップソケットの場合、lpOverlapped、lpCompletionRoutine、lpThreadId の各パラメーターは無視されます。トランスポートがすでに受信してバッファリングしているデータは、指定されたユーザーバッファーにコピーされます。ブロッキングソケットで、トランスポートが受信してバッファリングしたデータがまだない場合、呼び出しはデータを受信するまでブロックします。Windows Sockets 2 では、この関数に対する標準的なブロッキングタイムアウト機構は定義されていません。バイトストリームとして動作するプロトコルの場合、スタックは指定されたバッファー領域と受信済みデータ量の範囲で、可能な限り多くのデータを返そうとします。ただし、1 バイトでも受信すれば呼び出し元のブロックは解除されます。1 バイトを超えるデータが返される保証はありません。メッセージ指向として動作するプロトコルの場合は、呼び出し元のブロックを解除するために完全なメッセージが必要です。

プロトコルがバイトストリームとして動作するかどうかは、WSAPROTOCOL_INFO 構造体の XP1_MESSAGE_ORIENTED と XP1_PSEUDO_STREAM の設定、およびこの関数に渡される MSG_PARTIAL フラグの設定 (サポートするプロトコルの場合) によって決まります。関連する組み合わせを次の表にまとめます (アスタリスク (*) は、その場合にこのビットの設定が影響しないことを示します)。

XP1_MESSAGE_ORIENTED XP1_PSEUDO_STREAM MSG_PARTIAL 動作
未設定 * * バイトストリーム
* 設定 * バイトストリーム
設定 未設定 設定 バイトストリーム
設定 未設定 未設定 メッセージ指向

指定されたバッファーは、lpBuffers が指す配列に現れる順序で埋められ、隙間ができないように詰めて格納されます。

lpBuffers パラメーターが指す WSABUF 構造体の配列は一時的なものです。この操作がオーバーラップ方式で完了する場合、この呼び出しから戻る前に WSABUF 構造体へのポインターのこの配列を取り込むのは、サービスプロバイダーの責任です。これにより、Windows ソケット SPI クライアントはスタック上に WSABUF 配列を構築できます。

バイトストリーム型のソケット (たとえば SOCK_STREAM 型) の場合、受信データは、バッファーが満たされるか、接続がクローズされるか、内部にバッファリングされたデータが尽きるまでバッファーに格納されます。受信データがすべてのバッファーを満たすかどうかにかかわらず、オーバーラップソケットでは完了通知が発生します。メッセージ指向のソケット (たとえば SOCK_DGRAM 型) の場合、受信メッセージは指定されたバッファーの合計サイズまで格納され、オーバーラップソケットでは完了通知が発生します。メッセージが指定されたバッファーより大きい場合、バッファーにはメッセージの先頭部分が格納されます。サービスプロバイダーが MSG_PARTIAL 機能をサポートしている場合は、lpFlags に MSG_PARTIAL フラグが設定され、後続の受信操作でメッセージの残りを取得できます。MSG_PARTIAL がサポートされていなくてもプロトコルが信頼性のあるものであれば、LPWSPRecv はエラー WSAEMSGSIZE を生成し、より大きなバッファーで受信操作を行うことでメッセージ全体を取得できます。それ以外の場合 (つまり、プロトコルが信頼性を持たず、MSG_PARTIAL もサポートしない場合)、超過したデータは失われ、LPWSPRecv はエラー WSAEMSGSIZE を生成します。

コネクション指向のソケットの場合、LPWSPRecv は、ソケットがバイトストリームかメッセージ指向かに応じて、2 つの方法のいずれかで仮想回線の正常終了を示します。バイトストリームでは、読み取ったバイト数が 0 であることが正常なクローズを示し、以降バイトが読み取られることはありません。0 バイトのメッセージが許容されることが多いメッセージ指向のソケットでは、戻り値のエラーコード WSAEDISCON によって正常なクローズを示します。いずれの場合も、戻り値のエラーコード WSAECONNRESET は強制的なクローズが発生したことを示します。

lpFlags パラメーターを使用すると、対象のソケットに指定されたオプションを超えて、この関数呼び出しの動作に影響を与えることができます。つまり、この関数のセマンティクスは、ソケットオプションと lpFlags パラメーターによって決まります。後者は、次の値をビットごとの OR 演算子で組み合わせて構築します。

値 意味
MSG_PEEK 受信データを覗き見します。データはバッファーにコピーされますが、入力キューからは削除されません。このフラグは非オーバーラップソケットでのみ有効です。
MSG_OOB 帯域外 (OOB: Out Of Band) データを処理します。
MSG_PARTIAL このフラグはメッセージ指向のソケットでのみ使用します。出力時には、渡されたデータが送信側の送信したメッセージの一部であることを示します。メッセージの残りの部分は、後続の受信操作で渡されます。MSG_PARTIAL フラグがクリアされた後続の受信操作は、送信側のメッセージの終わりを示します。入力パラメーターとしての MSG_PARTIAL は、サービスプロバイダーがメッセージの一部しか受信していない場合でも受信操作を完了すべきであることを示します。

オーバーラップ操作がただちに完了した場合、LPWSPRecv は 0 を返し、lpNumberOfBytesRecvd パラメーターは受信したバイト数で更新され、lpFlags パラメーターが指すフラグビットも更新されます。オーバーラップ操作が正常に開始され、後で完了する場合、LPWSPRecv は SOCKET_ERROR を返し、エラーコード WSA_IO_PENDING を示します。この場合、lpNumberOfBytesRecvd と lpFlags は更新されません。オーバーラップ操作が完了すると、転送されたデータ量は、完了ルーチンの cbTransferred パラメーター (指定されている場合)、または LPWSPGetOverlappedResult の lpcbTransfer パラメーターによって示されます。フラグの値は、完了ルーチンの dwFlags パラメーターから取得するか、WSAGetOverlappedResult の lpdwFlags パラメーターを調べることで取得します。

プロバイダーは、直前の LPWSPRecv、LPWSPRecvFrom、LPWSPSend、LPWSPSendTo の完了ルーチン内からこの関数を呼び出せるようにする必要があります。ただし、特定のソケットについて、I/O 完了ルーチンを入れ子にすることはできません。これにより、時間に敏感なデータ送信を、プリエンプティブなコンテキスト内で完結させることができます。

lpOverlapped パラメーターは、オーバーラップ操作の間ずっと有効である必要があります。複数の I/O 操作が同時に未処理となる場合は、それぞれが個別のオーバーラップ構造体を参照する必要があります。WSAOverlapped 構造体については、専用のリファレンスページで定義されています。

lpCompletionRoutine パラメーターが null の場合、サービスプロバイダーは、lpOverlapped の hEvent メンバーに有効なイベントオブジェクトハンドルが格納されていれば、オーバーラップ操作の完了時にそれをシグナル状態にします。Windows ソケット SPI クライアントは、LPWSPGetOverlappedResult を使用してイベントオブジェクトを待機またはポーリングできます。

lpCompletionRoutine が null でない場合、hEvent メンバーは無視され、Windows ソケット SPI クライアントが完了ルーチンにコンテキスト情報を渡すために使用できます。lpCompletionRoutine に null を渡したクライアントが、同じオーバーラップ I/O 要求に対して後で WSAGetOverlappedResult を呼び出す場合、その WSAGetOverlappedResult の呼び出しで fWait パラメーターを TRUE に設定してはなりません。この場合、hEvent メンバーの用途は未定義であり、hEvent メンバーで待機しようとすると予測できない結果になります。

オーバーラップ操作の完了時に、クライアントが指定した完了ルーチンが呼び出されるように手配するのは、サービスプロバイダーの責任です。完了ルーチンは、オーバーラップ操作を開始したスレッドと同じコンテキストで実行する必要があるため、サービスプロバイダーから直接呼び出すことはできません。Ws2_32.dll は、完了ルーチンの呼び出しを容易にするために、非同期プロシージャ呼び出し (APC) の仕組みを提供しています。

サービスプロバイダーは、オーバーラップ操作の開始に使用された適切なスレッドおよびプロセスのコンテキストで関数が実行されるよう、WPUQueueApc を呼び出して手配します。この関数は、任意のプロセスおよびスレッドのコンテキストから呼び出すことができます。オーバーラップ操作の開始に使用されたスレッドやプロセスとは異なるコンテキストからでもかまいません。

WPUQueueApc は、入力パラメーターとして、WSATHREADID 構造体へのポインター (lpThreadId 入力パラメーターでプロバイダーに渡されたもの)、呼び出す APC 関数へのポインター、およびその後 APC 関数に渡されるコンテキスト値を受け取ります。利用できるコンテキスト値は 1 つだけであるため、APC 関数自体をクライアント指定の完了ルーチンにすることはできません。代わりに、サービスプロバイダーは独自の APC 関数へのポインターを指定する必要があります。その APC 関数は、渡されたコンテキスト値を使用してオーバーラップ操作に必要な結果情報にアクセスし、クライアントが指定した完了ルーチンを呼び出します。

クライアントが用意する完了ルーチンのプロトタイプは次のとおりです。

void CALLBACK 
CompletionRoutine(  
  IN DWORD           dwError, 
  IN DWORD           cbTransferred, 
  IN LPWSAOVERLAPPED lpOverlapped, 
  IN DWORD           dwFlags 
);

CompletionRoutine パラメーターは、クライアントが用意する関数名のプレースホルダーです。dwError は、lpOverlapped で示されるオーバーラップ操作の完了状態を指定します。cbTransferred パラメーターは、受信したバイト数を指定します。dwFlags には、受信操作がただちに完了していた場合に lpFlags に現れたであろう情報が格納されます。この関数は値を返しません。

完了ルーチンは任意の順序で呼び出される可能性があり、必ずしもオーバーラップ操作が完了した順序と同じとは限りません。ただし、ポストされたバッファーは、指定された順序どおりに埋められることが保証されます。

メモ

あるスレッドが開始したすべての I/O は、そのスレッドが終了すると取り消されます。オーバーラップソケットの場合、操作が完了する前にスレッドがクローズされると、保留中の非同期操作が失敗する可能性があります。詳細については ExitThread を参照してください。

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)