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 は、重複した操作が正常に開始され、完了が後で示されることを示します。 その他のエラー コードは、重複した操作が正常に開始されず、完了の兆候が発生しないことを示します。

エラー コード 意味
WSAECONNABORTED
仮想回線はタイムアウトまたはその他の障害のために切断されました。
WSAECONNRESET
ストリーム ソケットの場合、仮想回線はリモート側によってリセットされました。 ソケットが使用できないため、アプリケーションはソケットを閉じる必要があります。 UDP データグラム ソケットの場合、このエラーは、以前の送信操作で ICMP "ポートに到達できません" というメッセージが発生したことを示します。
WSAEFAULT
lpBufferslpNumberOfBytesSentlpOverlappedlpCompletionRoutine パラメーターは、ユーザー アドレス空間の有効な部分に完全には含まれていません。
WSAEINTR
ブロックしている Windows ソケット 1.1 呼び出しが WSACancelBlockingCall によって取り消されました。
WSAEINPROGRESS
ブロックしている Windows ソケット 1.1 呼び出しが進行中であるか、サービス プロバイダーがコールバック関数を処理しています。
WSAEINVAL
ソケットが bind でバインドされていないか、またはソケットが重複フラグで作成されていません。
WSAEMSGSIZE
ソケットはメッセージ指向であり、メッセージは基になるトランスポートでサポートされている最大値を超えています。
WSAENETDOWN
ネットワーク サブシステムが失敗しました。
WSAENETRESET
ストリーム ソケットの場合、操作の進行中にキープアライブ アクティビティが失敗を検出したため、接続が切断されました。 データグラム ソケットに関して、このエラーは有効期限が切れたことを示します。
WSAENOBUFS
Windows ソケット プロバイダーは、バッファー デッドロックを報告します。
WSAENOTCONN
ソケットは接続されていません。
WSAENOTSOCK
記述子はソケットではありません。
WSAEOPNOTSUPP
MSG_OOB 指定されましたが、ソケットがストリーム スタイル (型 SOCK_STREAMなど)、OOB データがこのソケットに関連付けられている通信ドメインでサポートされていない、 MSG_PARTIAL がサポートされていない、またはソケットが一方向であり、受信操作のみをサポートしています。
WSAESHUTDOWN
ソケットがシャットダウンされました。SD_SENDまたはSD_BOTHに設定された方法でシャットダウンが呼び出された後、ソケットで WSASend を実行することはできません。
WSAEWOULDBLOCK
Windows NT:

重複するソケット: 未解決の重複した I/O 要求が多すぎます。 非オーバーラップ ソケット: ソケットは非ブロッキングとしてマークされ、送信操作をすぐに完了することはできません。

WSANOTINITIALIZED
この関数を使用する前に 、WSAStartup 呼び出しが正常に行われる必要があります。
WSA_IO_PENDING
重複した操作が正常に開始され、後で完了が示されます。
WSA_OPERATION_ABORTED
ソケットのクローズ、 WSAIoctl での "SIO_FLUSH" コマンドの実行、または操作が完了する前に重複した要求を開始したスレッドが終了したため、重複した操作が取り消されました。 詳細については、「解説」を参照してください。

解説

WSASend 関数は、次の 2 つの重要な領域で標準送信関数以上の機能を提供します。

  • 重複するソケットと組み合わせて使用して、重複する 送信 操作を実行できます。
  • これにより、複数の 送信 バッファーを指定して、I/O の分散/収集の種類に適用できます。
WSASend 関数は、 で指定された接続指向ソケット上の 1 つ以上のバッファーから送信データを書き込む場合に使用されます。 ただし、 接続またはWSAConnect 関数を介して確立された既定のピア アドレスが規定されているコネクションレス ソケットでも使用できます。

ソケット関数によって作成された ソケット には、重複する属性が既定として含まれます。 wsASocket 関数によって作成されたソケットで、WSA_FLAG_OVERLAPPED ビット セットを使用して WSASocket に渡される dwFlags パラメーターを使用すると、 属性が重複します。 重複する属性を持つソケットの場合、 WSASend では 、lpOverlapped パラメーターと lpCompletionRoutine パラメーターの両方が NULL でない限り、重複した I/O が使用されます。 その場合、ソケットは重複していないソケットとして扱われます。 バッファーがトランスポートによって使用されると、ルーチンの完了またはイベント オブジェクトの設定を呼び出して、完了の兆候が発生します。 操作がすぐに完了しない場合は、完了ルーチンまたは WSAGetOverlappedResult を介して最終的な完了状態が取得されます。

lpOverlappedlpCompletionRoutine の両方が NULL の場合、この関数のソケットは重複していないソケットとして扱われます。

重複していないソケットの場合、最後の 2 つのパラメーター (lpOverlappedlpCompletionRoutine) は無視され、 WSASendsend と同じブロッキング セマンティクスを採用します。 データは、バッファーからトランスポートのバッファーにコピーされます。 ソケットが非ブロッキングでストリーム指向であり、トランスポートのバッファーに十分な領域がない場合、 WSASend はアプリケーションのバッファーの一部のみが消費された状態でを返します。 同じバッファー状況とブロッキング ソケットを考えると、 WSASend は、すべてのアプリケーション バッファーの内容が使用されるまでブロックします。

メモ ソケット オプション SO_RCVTIMEOSO_SNDTIMEO は、ブロッキング ソケットにのみ適用されます。
 
この関数が重複した方法で完了した場合、この呼び出しから戻る前に WSABUF 構造体をキャプチャするのは Winsock サービス プロバイダーの責任です。 これにより、アプリケーションは lpBuffers パラメーターによって指されるスタック ベースの WSABUF 配列を構築できます。

メッセージ指向ソケットの場合は、基になるプロバイダーの最大メッセージ サイズを超えないようにします。これは、socket オプション SO_MAX_MSG_SIZEの値を取得することで取得できます。 データが長すぎて基になるプロトコルをアトミックに通過できない場合は、 エラー WSAEMSGSIZE が返され、データは送信されません。

Windows Me/98/95: WSASend 関数は、16 個を超えるバッファーをサポートしていません。

メモWSASend が正常に完了しても、データが正常に配信されたことは示されません。
 

dwFlags の使用

dwFlags パラメーターを使用すると、関連付けられているソケットに指定されたオプションを超えて関数呼び出しの動作に影響を与えることができます。 つまり、この関数のセマンティクスは、ソケット オプションと dwFlags パラメーターによって決まります。 後者は、次の表に示す値のいずれかと共に、ビットごとの OR 演算子を使用して構築されます。
意味
MSG_DONTROUTE データをルーティングの対象にしないことを指定します。 Windows ソケット サービス プロバイダーは、このフラグを無視することを選択できます。
MSG_OOB SOCK_STREAMのみなど、ストリーム スタイルのソケットで OOB データを送信します。
MSG_PARTIAL lpBuffers に部分的なメッセージのみが含まれていることを指定します。 エラー コード WSAEOPNOTSUPP は、部分的なメッセージ転送をサポートしていないトランスポートによって返されることに注意してください。
 
メモlpOverlapped パラメーターを NULL に設定して WSASend などのブロッキング Winsock 呼び出しを発行する場合、Winsock は呼び出しを完了する前にネットワーク イベントを待機する必要がある場合があります。 Winsock は、この状況でアラート可能な待機を実行します。この待機は、同じスレッドでスケジュールされた非同期プロシージャ 呼び出し (APC) によって中断される可能性があります。 同じスレッドで進行中の Winsock 呼び出しを中断した APC 内で別のブロック Winsock 呼び出しを発行すると、未定義の動作が発生し、Winsock クライアントが試行することはできません。
 

重複するソケット I/O

重複した操作がすぐに完了すると、 WSASend は 0 の値を返し、 lpNumberOfBytesSent パラメーターは送信されたバイト数で更新されます。 重複した操作が正常に開始され、後で完了する場合、 WSASend はSOCKET_ERRORを返し、エラー コード のWSA_IO_PENDINGを示します。 この場合、 lpNumberOfBytesSent は更新されません。 重複する操作が完了すると、転送されるデータの量は、完了ルーチンの cbTransferred パラメーター (指定されている場合) または WSAGetOverlappedResultlpcbTransfer パラメーターを使用して示されます。
メモ 特定のスレッドによって開始されたすべての I/O は、そのスレッドが終了すると取り消されます。 重複するソケットの場合、操作が完了する前にスレッドが閉じられた場合、保留中の非同期操作が失敗する可能性があります。 詳細については、「 ExitThread」を参照してください。
 
重複した I/O を使用する WSASend 関数は、前の WSARecv、WSARecvFromWSASend、または WSASendTo 関数の完了ルーチン内から呼び出すことができます。 これにより、時間の影響を受けやすいデータ転送は、プリエンプティブ コンテキスト内で完全に行われます。

lpOverlapped パラメーターは、重複する操作の間有効である必要があります。 複数の I/O 操作が同時に未処理の場合は、それぞれが個別の WSAOVERLAPPED 構造体を参照する必要があります。

lpCompletionRoutine パラメーターが NULL の場合、lpOverlappedhEvent パラメーターには、有効なイベント オブジェクト ハンドルが含まれている場合、重複する操作が完了したときに通知されます。 アプリケーションでは、 WSAWaitForMultipleEvents または WSAGetOverlappedResult を使用して、イベント オブジェクトを待機またはポーリングできます。

lpCompletionRoutineNULL でない場合、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.1Windows 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

こちらもご覧ください

Wsabuf

WSACloseEvent

WSAConnect

WSACreateEvent

WSAGetOverlappedResult

WSAOVERLAPPED

WSASocket

WSAWaitForMultipleEvents

Winsock 関数

Winsock リファレンス

connect

送信

socket