LPWSPSENDTO
コールバックシグネチャ
INT LPWSPSENDTO(
SOCKET s,
WSABUF* lpBuffers,
DWORD dwBufferCount,
DWORD* lpNumberOfBytesSent,
DWORD dwFlags,
SOCKADDR* lpTo,
INT iTolen,
OVERLAPPED* lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
WSATHREADID* lpThreadId,
INT* lpErrno
);パラメーター
| フィールド | 型 | 説明 |
|---|---|---|
| s | SOCKET | ソケットを識別するディスクリプター。 |
| lpBuffers | WSABUF* | WSABUF 構造体の配列へのポインター。各 WSABUF 構造体には、バッファーへのポインターと、そのバッファーの長さ (バイト単位) が格納されます。Winsock アプリケーションでは、LPWSPSendTo 関数が呼び出された後、これらのバッファーはシステムが所有し、アプリケーションからアクセスすることはできません。各 WSABUF 構造体が参照するデータバッファーはシステムが所有しており、呼び出しが有効な間、アプリケーションからアクセスすることはできません。 |
| dwBufferCount | DWORD | lpBuffers 配列内の WSABUF 構造体の数。 |
| lpNumberOfBytesSent | DWORD* | この呼び出しで送信されたバイト数へのポインター。 |
| dwFlags | DWORD | 呼び出しの方法を指定するフラグのセット。 |
| lpTo | SOCKADDR* | sockaddr 構造体で表される、ターゲットソケットのアドレスへの省略可能なポインター。 |
| iTolen | INT | lpTo パラメーターが指すアドレスのサイズ (バイト単位)。 |
| lpOverlapped | OVERLAPPED* | WSAOverlapped 構造体へのポインター (非オーバーラップソケットでは無視されます)。 |
| lpCompletionRoutine | LPWSAOVERLAPPED_COMPLETION_ROUTINE | 送信操作が完了したときに呼び出される完了ルーチンへのポインター (非オーバーラップソケットでは無視されます)。 |
| lpThreadId | WSATHREADID* | プロバイダーが後続の WPUQueueApc の呼び出しで使用する WSATHREADID 構造体へのポインター。プロバイダーは、WPUQueueApc 関数が戻るまで、参照先の WSATHREADID 構造体を (そのポインターではなく構造体そのものを) 保持しておく必要があります。 |
| lpErrno | INT* | エラーコードへのポインター。 |
公式ドキュメント
LPWSPSendTo 関数は、オーバーラップ I/O を使用して特定の宛先にデータを送信します。
戻り値
エラーが発生せず、操作が即座に完了した場合、LPWSPSendTo は 0 を返します。この場合、完了ルーチンが指定されていれば、それは既にキューに登録されている点に注意してください。それ以外の場合は SOCKET_ERROR が返され、具体的なエラーコードは lpErrno で取得できます。エラーコード WSA_IO_PENDING は、オーバーラップ操作が正常に開始され、完了が後で通知されることを示します。それ以外のエラーコードは、オーバーラップ操作が開始されておらず、完了通知も発生しないことを示します。
| エラーコード | 意味 |
|---|---|
| ネットワークサブシステムで障害が発生しました。 | |
| 要求されたアドレスはブロードキャストアドレスですが、適切なフラグが設定されていませんでした。 | |
| (ブロッキング) 呼び出しが LPWSPCancelBlockingCall によってキャンセルされました。 | |
| ブロッキング Windows Sockets 呼び出しが進行中であるか、サービスプロバイダーがコールバック関数をまだ処理しています。 | |
| lpBuffers または lpTo パラメーターがユーザーアドレス空間の一部ではないか、lpTo パラメーターが小さすぎます。 | |
| 操作の進行中に keep-alive の動作が障害を検出したため、接続が切断されました。 | |
| Windows Sockets プロバイダーがバッファーのデッドロックを報告しています。 | |
| ソケットが接続されていません (コネクション指向のソケットのみ)。 | |
| ディスクリプターがソケットではありません。 | |
| MSG_OOB が指定されましたが、ソケットが SOCK_STREAM 型のようなストリーム形式ではない、このソケットに関連付けられた通信ドメインで OOB データがサポートされていない、MSG_PARTIAL がサポートされていない、またはソケットが単方向で受信操作のみをサポートしています。 | |
| ソケットはシャットダウンされています。how に SD_SEND または SD_BOTH を指定して LPWSPShutdown が呼び出された後は、そのソケットで LPWSPSendTo を使用することはできません。 | |
| Windows NT: オーバーラップソケットの場合: 未処理のオーバーラップ I/O 要求が多すぎます。非オーバーラップソケットの場合: ソケットが非ブロッキングとしてマークされており、送信操作を即座に完了できません。 | |
| ソケットがメッセージ指向であり、メッセージが基になるトランスポートでサポートされる最大サイズを超えています。 | |
| ソケットが LPWSPBind でバインドされていないか、ソケットがオーバーラップフラグを指定して作成されていません。 | |
| タイムアウトまたはその他の障害により、仮想回線が終了しました。 | |
| 仮想回線がリモート側によってリセットされました。 | |
| リモートアドレスが有効なアドレスではありません (例: ADDR_ANY)。 | |
| 指定されたファミリのアドレスは、このソケットでは使用できません。 | |
| 宛先アドレスが必要です。 | |
| 現時点では、このホストからネットワークに到達できません。 | |
| ソケットが閉じられたか、LPWSPIoctl で SIO_FLUSH コマンドが実行されたため、オーバーラップ操作がキャンセルされました。 |
解説(Remarks)
LPWSPSendTo 関数は通常、s で指定されたコネクションレスソケットで使用し、1 つ以上のバッファーに格納されたデータグラムを、lpTo パラメーターで識別される特定のピアソケットへ送信します。コネクションレスソケットが事前に LPWSPConnect 関数で特定のアドレスに接続されている場合でも、lpTo はそのデータグラムに限って宛先アドレスを上書きします。コネクション指向のソケットでは、lpTo と iToLen パラメーターは無視され、この場合 LPWSPSendTo 関数は LPWSPSend と等価です。
オーバーラップソケット (WSA_FLAG_OVERLAPPED フラグを指定して LPWSPSocket で作成されたソケット) では、この処理はオーバーラップ I/O を使用して行われます。ただし、lpOverlapped と lpCompletionRoutine の両方が NULL の場合、そのソケットは非オーバーラップソケットとして扱われます。指定されたバッファーがトランスポートによって消費されると、完了通知 (完了ルーチンの呼び出し、またはイベントオブジェクトのシグナル設定) が発生します。操作が即座に完了しない場合、最終的な完了状態は完了ルーチンまたは LPWSPGetOverlappedResult を通じて取得します。
非オーバーラップソケットでは、lpOverlapped、lpCompletionRoutine、lpThreadId の各パラメーターは無視され、LPWSPSendTo は通常の同期的なセマンティクスに従います。データは、指定されたバッファーからトランスポートのバッファーへコピーされます。ソケットが非ブロッキングかつストリーム指向で、トランスポートのバッファーに十分な空きがない場合、LPWSPSendTo は Windows Sockets SPI クライアントのバッファーの一部だけが消費された状態で戻ります。同じバッファー状況でブロッキングソケットの場合、LPWSPSendTo は Windows Sockets SPI クライアントのバッファーの内容がすべて消費されるまでブロックします。
lpBuffers パラメーターが指す WSABUF 構造体の配列は一時的なものです。この操作がオーバーラップ方式で完了する場合、この呼び出しから戻る前にこれらの WSABUF 構造体を取り込むのは、サービスプロバイダーの責任です。これにより、アプリケーションはスタック上に WSABUF の配列を構築できます。
メッセージ指向のソケットでは、基になるトランスポートの最大メッセージサイズを超えないように注意する必要があります。この値は、ソケットオプション SO_MAX_MSG_SIZE の値を取得することで得られます。データが長すぎて、基になるプロトコルでアトミックに渡せない場合は、エラー WSAEMSGSIZE が返され、データは送信されません。
LPWSPSendTo が正常に完了しても、データが正常に配信されたことを示すわけではない点に注意してください。
iFlags パラメーターを使用すると、関連付けられたソケットに指定されたオプションの範囲を超えて、この関数呼び出しの動作に影響を与えることができます。つまり、この関数のセマンティクスは、ソケットオプションと dwFlags パラメーターによって決まります。後者は、次の値をビットごとの OR 演算子で組み合わせて構成します。
| 値 | 意味 |
|---|---|
| MSG_DONTROUTE | データをルーティングの対象としないことを指定します。Windows Sockets サービスプロバイダーは、このフラグを無視することもできます。 |
| MSG_OOB | OOB データを送信します (SOCK_STREAM などのストリーム形式のソケットのみ)。 |
| MSG_PARTIAL | lpBuffers がメッセージの一部のみを含むことを指定します。部分的なメッセージ送信をサポートしないトランスポートでは、エラーコード WSAEOPNOTSUPP が返される点に注意してください。 |
オーバーラップ操作が即座に完了した場合、LPWSPSendTo は 0 を返し、lpNumberOfBytesSent パラメーターは送信されたバイト数に更新されます。オーバーラップ操作が正常に開始され、後で完了する場合、LPWSPSendTo は SOCKET_ERROR を返し、エラーコード WSA_IO_PENDING を示します。この場合、lpNumberOfBytesSent は更新されません。オーバーラップ操作が完了すると、転送されたデータ量は、完了ルーチンの cbTransferred パラメーター (指定されている場合)、または LPWSPGetOverlappedResult の lpcbTransfer パラメーターを通じて示されます。
プロバイダーは、直前の LPWSPRecv、LPWSPRecvFrom、LPWSPSend、または LPWSPSendTo 関数の完了ルーチン内から、この関数が呼び出されることを許可する必要があります。ただし、特定のソケットについて、I/O 完了ルーチンを入れ子にすることはできません。これにより、時間的制約のあるデータ送信をプリエンプティブなコンテキスト内で完結させることができます。
lpOverlapped パラメーターは、オーバーラップ操作が継続している間、有効である必要があります。複数の I/O 操作が同時に未処理の状態にある場合は、それぞれが別個のオーバーラップ構造体を参照する必要があります。WSAOverlapped 構造体は、専用のリファレンスページで定義されています。
lpCompletionRoutine パラメーターが null の場合、サービスプロバイダーは、lpOverlapped の hEvent メンバーが有効なイベントオブジェクトハンドルを保持していれば、オーバーラップ操作の完了時にそれをシグナル状態にします。Windows Sockets SPI クライアントは、LPWSPGetOverlappedResult を使用して、そのイベントオブジェクトを待機またはポーリングできます。
lpCompletionRoutine が null でない場合、hEvent メンバーは無視され、Windows Sockets SPI クライアントが完了ルーチンにコンテキスト情報を渡すために使用できます。null 以外の lpCompletionRoutine を渡したクライアントが、同じオーバーラップ 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 の値は 0 になります。この関数は値を返しません。
完了ルーチンは任意の順序で呼び出される可能性があり、必ずしもオーバーラップ操作が完了した順序と同じとは限りません。ただしサービスプロバイダーは、ポストされたバッファーが指定された順序どおりに送信されることをクライアントに保証します。
あるスレッドが開始したすべての I/O は、そのスレッドが終了したときにキャンセルされます。オーバーラップソケットでは、操作が完了する前にスレッドが閉じられると、保留中の非同期操作が失敗する可能性があります。詳細については、ExitThread を参照してください。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)