WSASend 関数 (winsock2.h)
WSASend 関数は、接続されているソケットでデータを送信します。
構文
int WSAAPI WSASend(
[in] SOCKET s,
[in] LPWSABUF lpBuffers,
[in] DWORD dwBufferCount,
[out] LPDWORD lpNumberOfBytesSent,
[in] DWORD dwFlags,
[in] LPWSAOVERLAPPED lpOverlapped,
[in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
パラメーター
[in] s
接続されているソケットを識別する記述子。
[in] lpBuffers
WSABUF 構造体の配列へのポインター。 各 WSABUF 構造体には、バッファーへのポインターとバッファーの長さ (バイト単位) が含まれます。 Winsock アプリケーションの場合、 WSASend 関数が呼び出されると、システムはこれらのバッファーを所有し、アプリケーションがそれらにアクセスできない可能性があります。 この配列は、送信操作の間有効なままである必要があります。
[in] dwBufferCount
lpBuffers 配列内の WSABUF 構造体の数。
[out] lpNumberOfBytesSent
I/O 操作が直ちに完了した場合に、この呼び出しによって送信される数 (バイト単位) へのポインター。
lpOverlapped パラメーターが NULL でない場合は、このパラメーターに NULL を使用して、誤った結果を回避します。 このパラメーターは、lpOverlapped パラメーターが NULL でない場合にのみ NULL にすることができます。
[in] dwFlags
WSASend 関数呼び出しの動作を変更するために使用されるフラグ。 詳細については、「解説」セクションの 「dwFlags の使用」を参照してください。
[in] lpOverlapped
WSAOVERLAPPED 構造体へのポインター。 このパラメーターは、オーバーラップされていないソケットでは無視されます。
[in] lpCompletionRoutine
種類: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
送信操作が完了したときに呼び出される完了ルーチンへのポインター。 このパラメーターは、オーバーラップされていないソケットでは無視されます。
戻り値
エラーが発生せず、送信操作がすぐに完了した場合、 WSASend は 0 を返します。 この場合、呼び出し元のスレッドが警告可能な状態になると、完了ルーチンは既に呼び出されるようにスケジュールされています。 それ以外の場合は、 SOCKET_ERROR の値が返され、 WSAGetLastError を呼び出すことによって特定のエラー コードを取得できます。 エラー コード WSA_IO_PENDING は、重複した操作が正常に開始され、完了が後で示されることを示します。 その他のエラー コードは、重複した操作が正常に開始されず、完了の兆候が発生しないことを示します。
エラー コード | 意味 |
---|---|
仮想回線はタイムアウトまたはその他の障害のために切断されました。 | |
ストリーム ソケットの場合、仮想回線はリモート側によってリセットされました。 ソケットが使用できないため、アプリケーションはソケットを閉じる必要があります。 UDP データグラム ソケットの場合、このエラーは、以前の送信操作で ICMP "ポートに到達できません" というメッセージが発生したことを示します。 | |
lpBuffers、lpNumberOfBytesSent、lpOverlapped、lpCompletionRoutine パラメーターは、ユーザー アドレス空間の有効な部分に完全には含まれていません。 | |
ブロックしている Windows ソケット 1.1 呼び出しが WSACancelBlockingCall によって取り消されました。 | |
ブロックしている Windows ソケット 1.1 呼び出しが進行中であるか、サービス プロバイダーがコールバック関数を処理しています。 | |
ソケットが bind でバインドされていないか、またはソケットが重複フラグで作成されていません。 | |
ソケットはメッセージ指向であり、メッセージは基になるトランスポートでサポートされている最大値を超えています。 | |
ネットワーク サブシステムが失敗しました。 | |
ストリーム ソケットの場合、操作の進行中にキープアライブ アクティビティが失敗を検出したため、接続が切断されました。 データグラム ソケットに関して、このエラーは有効期限が切れたことを示します。 | |
Windows ソケット プロバイダーは、バッファー デッドロックを報告します。 | |
ソケットは接続されていません。 | |
記述子はソケットではありません。 | |
MSG_OOB 指定されましたが、ソケットがストリーム スタイル (型 SOCK_STREAMなど)、OOB データがこのソケットに関連付けられている通信ドメインでサポートされていない、 MSG_PARTIAL がサポートされていない、またはソケットが一方向であり、受信操作のみをサポートしています。 | |
ソケットがシャットダウンされました。SD_SENDまたはSD_BOTHに設定された方法でシャットダウンが呼び出された後、ソケットで WSASend を実行することはできません。 | |
Windows NT:
重複するソケット: 未解決の重複した I/O 要求が多すぎます。 非オーバーラップ ソケット: ソケットは非ブロッキングとしてマークされ、送信操作をすぐに完了することはできません。 |
|
この関数を使用する前に 、WSAStartup 呼び出しが正常に行われる必要があります。 | |
重複した操作が正常に開始され、後で完了が示されます。 | |
ソケットのクローズ、 WSAIoctl での "SIO_FLUSH" コマンドの実行、または操作が完了する前に重複した要求を開始したスレッドが終了したため、重複した操作が取り消されました。 詳細については、「解説」を参照してください。 |
解説
WSASend 関数は、次の 2 つの重要な領域で標準送信関数以上の機能を提供します。
WSASend 関数は、 で指定された接続指向ソケット上の 1 つ以上のバッファーから送信データを書き込む場合に使用されます。 ただし、 接続またはWSAConnect 関数を介して確立された既定のピア アドレスが規定されているコネクションレス ソケットでも使用できます。ソケット関数によって作成された ソケット には、重複する属性が既定として含まれます。 wsASocket 関数によって作成されたソケットで、WSA_FLAG_OVERLAPPED ビット セットを使用して WSASocket に渡される dwFlags パラメーターを使用すると、 属性が重複します。 重複する属性を持つソケットの場合、 WSASend では 、lpOverlapped パラメーターと lpCompletionRoutine パラメーターの両方が NULL でない限り、重複した I/O が使用されます。 その場合、ソケットは重複していないソケットとして扱われます。 バッファーがトランスポートによって使用されると、ルーチンの完了またはイベント オブジェクトの設定を呼び出して、完了の兆候が発生します。 操作がすぐに完了しない場合は、完了ルーチンまたは WSAGetOverlappedResult を介して最終的な完了状態が取得されます。
lpOverlapped と lpCompletionRoutine の両方が NULL の場合、この関数のソケットは重複していないソケットとして扱われます。
重複していないソケットの場合、最後の 2 つのパラメーター (lpOverlapped、 lpCompletionRoutine) は無視され、 WSASend は send と同じブロッキング セマンティクスを採用します。 データは、バッファーからトランスポートのバッファーにコピーされます。 ソケットが非ブロッキングでストリーム指向であり、トランスポートのバッファーに十分な領域がない場合、 WSASend はアプリケーションのバッファーの一部のみが消費された状態でを返します。 同じバッファー状況とブロッキング ソケットを考えると、 WSASend は、すべてのアプリケーション バッファーの内容が使用されるまでブロックします。
メッセージ指向ソケットの場合は、基になるプロバイダーの最大メッセージ サイズを超えないようにします。これは、socket オプション SO_MAX_MSG_SIZEの値を取得することで取得できます。 データが長すぎて基になるプロトコルをアトミックに通過できない場合は、 エラー WSAEMSGSIZE が返され、データは送信されません。
Windows Me/98/95: WSASend 関数は、16 個を超えるバッファーをサポートしていません。
dwFlags の使用
dwFlags パラメーターを使用すると、関連付けられているソケットに指定されたオプションを超えて関数呼び出しの動作に影響を与えることができます。 つまり、この関数のセマンティクスは、ソケット オプションと dwFlags パラメーターによって決まります。 後者は、次の表に示す値のいずれかと共に、ビットごとの OR 演算子を使用して構築されます。値 | 意味 |
---|---|
MSG_DONTROUTE | データをルーティングの対象にしないことを指定します。 Windows ソケット サービス プロバイダーは、このフラグを無視することを選択できます。 |
MSG_OOB | SOCK_STREAMのみなど、ストリーム スタイルのソケットで OOB データを送信します。 |
MSG_PARTIAL | lpBuffers に部分的なメッセージのみが含まれていることを指定します。 エラー コード WSAEOPNOTSUPP は、部分的なメッセージ転送をサポートしていないトランスポートによって返されることに注意してください。 |
重複するソケット I/O
重複した操作がすぐに完了すると、 WSASend は 0 の値を返し、 lpNumberOfBytesSent パラメーターは送信されたバイト数で更新されます。 重複した操作が正常に開始され、後で完了する場合、 WSASend はSOCKET_ERRORを返し、エラー コード のWSA_IO_PENDINGを示します。 この場合、 lpNumberOfBytesSent は更新されません。 重複する操作が完了すると、転送されるデータの量は、完了ルーチンの cbTransferred パラメーター (指定されている場合) または WSAGetOverlappedResult の lpcbTransfer パラメーターを使用して示されます。lpOverlapped パラメーターは、重複する操作の間有効である必要があります。 複数の I/O 操作が同時に未処理の場合は、それぞれが個別の WSAOVERLAPPED 構造体を参照する必要があります。
lpCompletionRoutine パラメーターが NULL の場合、lpOverlapped の hEvent パラメーターには、有効なイベント オブジェクト ハンドルが含まれている場合、重複する操作が完了したときに通知されます。 アプリケーションでは、 WSAWaitForMultipleEvents または WSAGetOverlappedResult を使用して、イベント オブジェクトを待機またはポーリングできます。
lpCompletionRoutine が NULL でない場合、hEvent パラメーターは無視され、アプリケーションがコンテキスト情報を完了ルーチンに渡すために使用できます。 NULL 以外の lpCompletionRoutine を渡し、その後、同じ重複した I/O 要求に対して WSAGetOverlappedResult を呼び出す呼び出し元は、WSAGetOverlappedResult の呼び出しに対して fWait パラメーターを TRUE に設定することはできません。 この場合、 hEvent パラメーターの使用は未定義であり、 hEvent パラメーターを待機しようとすると予期しない結果が生成されます。
完了ルーチンは、Windows ファイル I/O 完了ルーチンに規定されているのと同じ規則に従います。 fAlertable パラメーターが TRUE に設定された関数 WSAWaitForMultipleEvents が呼び出されたときに、スレッドがアラート可能な待機状態になるまで、完了ルーチンは呼び出されません。
トランスポート プロバイダーを使用すると、アプリケーションはソケット I/O 完了ルーチンのコンテキスト内から送受信操作を呼び出し、特定のソケットに対して I/O 完了ルーチンが入れ子にならないことを保証できます。 これにより、時間の影響を受けやすいデータ転送は、プリエンプティブ コンテキスト内で完全に行われます。
次の C++ コード例は、完了ルーチンのプロトタイプです。
void CALLBACK CompletionROUTINE(
IN DWORD dwError,
IN DWORD cbTransferred,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD dwFlags
);
CompletionRoutine 関数は、アプリケーション定義またはライブラリ定義の関数名のプレースホルダーです。 dwError パラメーターは、lpOverlapped で示されているように、重複した操作の完了状態を指定します。 cbTransferred は、送信されたバイト数を指定します。 現在、フラグ値は定義されておらず、 dwFlags は 0 になります。 この関数は値を返しません。
この関数から戻って、このソケットに対して別の保留中の完了ルーチンを呼び出すことができます。 警告可能なスレッドの待機が WSA_IO_COMPLETIONの戻りコードで満たされる前に、すべての待機完了ルーチンが呼び出されます。 完了ルーチンは任意の順序で呼び出すことができます。重複する操作が完了した順序と同じ順序であるとは限りません。 ただし、ポストされたバッファーは、指定された順序で送信することが保証されます。
WSASend への呼び出しの順序は、バッファーがトランスポート層に送信される順序でもあります。 WSASend は、異なるスレッドから同じストリーム指向ソケットで同時に呼び出さないでください。一部の Winsock プロバイダーでは、大きな送信要求が複数の送信に分割される可能性があり、これにより、同じストリーム指向ソケット上の複数の同時送信要求から意図しないデータインターリーブが発生する可能性があるためです。
コード例
次のコード例は、重複した I/O モードで WSASend 関数を使用する方法を示しています。#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
#define DATA_BUFSIZE 4096
#define SEND_COUNT 10
int __cdecl main()
{
WSADATA wsd;
struct addrinfo *result = NULL;
struct addrinfo hints;
WSAOVERLAPPED SendOverlapped;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET AcceptSocket = INVALID_SOCKET;
WSABUF DataBuf;
DWORD SendBytes;
DWORD Flags;
char buffer[DATA_BUFSIZE];
int err = 0;
int rc, i;
// Load Winsock
rc = WSAStartup(MAKEWORD(2, 2), &wsd);
if (rc != 0) {
printf("Unable to load Winsock: %d\n", rc);
return 1;
}
// Make sure the hints struct is zeroed out
SecureZeroMemory((PVOID) & hints, sizeof(struct addrinfo));
// Initialize the hints to obtain the
// wildcard bind address for IPv4
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
rc = getaddrinfo(NULL, "27015", &hints, &result);
if (rc != 0) {
printf("getaddrinfo failed with error: %d\n", rc);
return 1;
}
ListenSocket = socket(result->ai_family,
result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
return 1;
}
rc = bind(ListenSocket, result->ai_addr, (int) result->ai_addrlen);
if (rc == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return 1;
}
rc = listen(ListenSocket, 1);
if (rc == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return 1;
}
// Accept an incoming connection request
AcceptSocket = accept(ListenSocket, NULL, NULL);
if (AcceptSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return 1;
}
printf("Client Accepted...\n");
// Make sure the SendOverlapped struct is zeroed out
SecureZeroMemory((PVOID) & SendOverlapped, sizeof (WSAOVERLAPPED));
// Create an event handle and setup the overlapped structure.
SendOverlapped.hEvent = WSACreateEvent();
if (SendOverlapped.hEvent == NULL) {
printf("WSACreateEvent failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
closesocket(AcceptSocket);
return 1;
}
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
for (i = 0; i < SEND_COUNT; i++) {
rc = WSASend(AcceptSocket, &DataBuf, 1,
&SendBytes, 0, &SendOverlapped, NULL);
if ((rc == SOCKET_ERROR) &&
(WSA_IO_PENDING != (err = WSAGetLastError()))) {
printf("WSASend failed with error: %d\n", err);
break;
}
rc = WSAWaitForMultipleEvents(1, &SendOverlapped.hEvent, TRUE, INFINITE,
TRUE);
if (rc == WSA_WAIT_FAILED) {
printf("WSAWaitForMultipleEvents failed with error: %d\n",
WSAGetLastError());
break;
}
rc = WSAGetOverlappedResult(AcceptSocket, &SendOverlapped, &SendBytes,
FALSE, &Flags);
if (rc == FALSE) {
printf("WSASend failed with error: %d\n", WSAGetLastError());
break;
}
printf("Wrote %d bytes\n", SendBytes);
WSAResetEvent(SendOverlapped.hEvent);
}
WSACloseEvent(SendOverlapped.hEvent);
closesocket(AcceptSocket);
closesocket(ListenSocket);
freeaddrinfo(result);
WSACleanup();
return 0;
}
Windows Phone 8: この関数は、Windows Phone 8 以降のWindows Phone ストア アプリでサポートされています。
Windows 8.1とWindows Server 2012 R2: この関数は、Windows 8.1、Windows Server 2012 R2 以降の Windows ストア アプリでサポートされています。
要件
要件 | 値 |
---|---|
サポートされている最小のクライアント | Windows 8.1、 Windows Vista [デスクトップ アプリ |UWP アプリ] |
サポートされている最小のサーバー | Windows Server 2003 [デスクトップ アプリのみ | UWP アプリ] |
対象プラットフォーム | Windows |
ヘッダー | winsock2.h |
Library | Ws2_32.lib |
[DLL] | Ws2_32.dll |