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