WSASend-Funktion (winsock2.h)

Die WSASend-Funktion sendet Daten auf einem verbundenen Socket.

Syntax

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
);

Parameter

[in] s

Ein Deskriptor, der einen verbundenen Socket identifiziert.

[in] lpBuffers

Ein Zeiger auf ein Array von WSABUF-Strukturen . Jede WSABUF-Struktur enthält einen Zeiger auf einen Puffer und die Länge des Puffers in Bytes. Bei einer Winsock-Anwendung besitzt das System nach dem Aufruf der WSASend-Funktion diese Puffer, und die Anwendung greift möglicherweise nicht darauf zu. Dieses Array muss für die Dauer des Sendevorgangs gültig bleiben.

[in] dwBufferCount

Die Anzahl der WSABUF-Strukturen im lpBuffers-Array .

[out] lpNumberOfBytesSent

Ein Zeiger auf die Zahl in Bytes, die von diesem Aufruf gesendet wird, wenn der E/A-Vorgang sofort abgeschlossen wird.

Verwenden Sie NULL für diesen Parameter, wenn der lpOverlapped-Parameter nicht NULL ist, um potenziell fehlerhafte Ergebnisse zu vermeiden. Dieser Parameter kann nur NULL sein, wenn der lpOverlapped-Parameter nicht NULL ist.

[in] dwFlags

Die Flags, die verwendet werden, um das Verhalten des WSASend-Funktionsaufrufs zu ändern. Weitere Informationen finden Sie unter Verwenden von dwFlags im Abschnitt Hinweise.

[in] lpOverlapped

Ein Zeiger auf eine WSAOVERLAPPED-Struktur . Dieser Parameter wird für nicht überlappte Sockets ignoriert.

[in] lpCompletionRoutine

Typ: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE

Ein Zeiger auf die Vervollständigungsroutine, die aufgerufen wird, wenn der Sendevorgang abgeschlossen wurde. Dieser Parameter wird für nicht überlappte Sockets ignoriert.

Rückgabewert

Wenn kein Fehler auftritt und der Sendevorgang sofort abgeschlossen wurde, gibt WSASend null zurück. In diesem Fall wurde der Aufruf der Vervollständigungsroutine bereits geplant, sobald sich der aufrufende Thread im warnbaren Zustand befindet. Andernfalls wird der Wert SOCKET_ERROR zurückgegeben, und ein bestimmter Fehlercode kann durch Aufrufen von WSAGetLastError abgerufen werden. Der Fehlercode WSA_IO_PENDING gibt an, dass der überlappende Vorgang erfolgreich initiiert wurde und dass die Vervollständigung zu einem späteren Zeitpunkt angezeigt wird. Jeder andere Fehlercode gibt an, dass der überlappende Vorgang nicht erfolgreich initiiert wurde und keine Vervollständigungsanzeige auftritt.

Fehlercode Bedeutung
WSAECONNABORTED
Timeout- oder anderer Fehler. Die virtuelle Verbindung wurde beendet.
WSAECONNRESET
Bei einem Streamsocket wurde die virtuelle Verbindung von der Remoteseite zurückgesetzt. Die Anwendung sollte den Socket schließen, weil er nicht mehr verwendbar ist. Bei einem UDP-Datagrammsocket würde dieser Fehler darauf hindeuten, dass ein vorheriger Sendevorgang zu einer ICMP-Meldung "Port Unreachable" geführt hat.
WSAEFAULT
Die Parameter lpBuffers, lpNumberOfBytesSent, lpOverlapped, lpCompletionRoutine sind nicht vollständig in einem gültigen Teil des Benutzeradressraums enthalten.
WSAEINTR
Ein blockierender Windows Socket 1.1-Aufruf wurde über WSACancelBlockingCall abgebrochen.
WSAEINPROGRESS
Ein blockierter Windows Sockets 1.1-Aufruf wird ausgeführt, oder der Dienstanbieter verarbeitet weiterhin eine Rückruffunktion.
WSAEINVAL
Der Socket wurde nicht an bind gebunden, oder der Socket wird nicht mit dem überlappenden Flag erstellt.
WSAEMSGSIZE
Der Socket ist nachrichtenorientiert, und die Nachricht ist größer als das maximum, das vom zugrunde liegenden Transport unterstützt wird.
WSAENETDOWN
Beim Netzwerksubsystem ist ein Fehler aufgetreten.
WSAENETRESET
Bei einem Streamsocket wurde die Verbindung unterbrochen, weil die Keep-Alive-Aktivität einen Fehler erkennt, während der Vorgang ausgeführt wurde. Für einen Datagrammsocket zeigt dieser Fehler an, dass die Gültigkeitsdauer abgelaufen ist.
WSAENOBUFS
Der Windows Sockets-Anbieter meldet einen Puffer-Deadlock.
WSAENOTCONN
Der Socket ist nicht verbunden.
WSAENOTSOCK
Der Deskriptor ist kein Socket.
WSAEOPNOTSUPP
MSG_OOB angegeben wurde, aber der Socket keine Streamart ist, z. B. typ SOCK_STREAM, werden OOB-Daten in der diesem Socket zugeordneten Kommunikationsdomäne nicht unterstützt, MSG_PARTIAL wird nicht unterstützt, oder der Socket ist unidirektional und unterstützt nur Empfangsvorgänge.
WSAESHUTDOWN
Der Socket wurde heruntergefahren. Es ist nicht möglich, WSASend für einen Socket zu verwenden, nachdem das Herunterfahren aufgerufen wurde und wie auf SD_SEND oder SD_BOTH festgelegt ist.
WSAEWOULDBLOCK
Windows NT:

Überlappende Sockets: Es gibt zu viele ausstehende überlappende E/A-Anforderungen. Nicht überlappte Sockets: Der Socket ist als nicht blockiert gekennzeichnet, und der Sendevorgang kann nicht sofort abgeschlossen werden.

WSANOTINITIALISIERT
Vor der Verwendung dieser Funktion muss ein erfolgreicher WSAStartup-Aufruf erfolgen.
WSA_IO_PENDING
Ein überlappender Vorgang wurde erfolgreich eingeleitet, und der Abschluss wird zu einem späteren Zeitpunkt angezeigt.
WSA_OPERATION_ABORTED
Der überlappende Vorgang wurde aufgrund des Schließens des Sockets, der Ausführung des Befehls "SIO_FLUSH" in WSAIoctl oder des Threads, der die überlappende Anforderung initiiert hat, abgebrochen, bevor der Vorgang abgeschlossen wurde. Weitere Informationen finden Sie im Abschnitt mit Hinweisen.

Bemerkungen

Die WSASend-Funktion bietet Funktionen über die Standardsendefunktion hinaus in zwei wichtigen Bereichen:

  • Es kann in Verbindung mit überlappenden Sockets verwendet werden, um überlappende Sendevorgänge auszuführen.
  • Dadurch können mehrere Sendepuffer angegeben werden, sodass sie auf den Scatter/Gather-Typ von E/A anwendbar sind.
Die WSASend-Funktion wird verwendet, um ausgehende Daten aus einem oder mehreren Puffern auf einen verbindungsorientierten Socket zu schreiben, der durch s angegeben wird. Es kann jedoch auch für verbindungslose Sockets verwendet werden, die über eine festgelegte Standard-Peeradresse verfügen, die über die Connect - oder WSAConnect-Funktion eingerichtet wurde.

Ein socket, der von der Socketfunktion erstellt wurde, weist das überlappende Attribut als Standard auf. Ein Socket, der von der WSASocket-Funktion erstellt wird und der dwFlags-Parameter an WSASocket übergeben wird, mit dem WSA_FLAG_OVERLAPPED Bitsatz, weist das überlappende Attribut auf. Für Sockets mit dem überlappenden Attribut verwendet WSASend überlappende E/A, es sei denn, die Parameter lpOverlapped und lpCompletionRoutine sind NULL. In diesem Fall wird der Socket als nicht überlappender Socket behandelt. Es wird eine Vervollständigungsanzeige angezeigt, die die Vervollständigung einer Routine oder Einstellung eines Ereignisobjekts aufruft, wenn die Puffer vom Transport verbraucht wurden. Wenn der Vorgang nicht sofort abgeschlossen wird, wird der endgültige Abschluss status über die Vervollständigungsroutine oder WSAGetOverlappedResult abgerufen.

Wenn sowohl lpOverlapped als auch lpCompletionRoutineNULL sind, wird der Socket in dieser Funktion als nicht überlappender Socket behandelt.

Bei nicht überlappenden Sockets werden die letzten beiden Parameter (lpOverlapped, lpCompletionRoutine) ignoriert, und WSASend übernimmt die gleiche blockierende Semantik wie send. Daten werden aus den Puffern in den Puffer des Transports kopiert. Wenn der Socket nicht blockierend und streamorientiert ist und nicht genügend Speicherplatz im Puffer des Transports vorhanden ist, wird WSASend zurückgegeben, wobei nur ein Teil der Puffer der Anwendung verbraucht wurde. Bei derselben Puffersituation und einem blockierenden Socket wird WSASend blockiert, bis der gesamte Inhalt des Anwendungspuffers verbraucht wurde.

Hinweis Die Socketoptionen SO_RCVTIMEO und SO_SNDTIMEO nur für blockierende Sockets gelten.
 
Wenn diese Funktion überlappend ausgeführt wird, liegt es in der Verantwortung des Winsock-Dienstanbieters, die WSABUF-Strukturen zu erfassen, bevor sie von diesem Aufruf zurückgegeben werden. Dadurch können Anwendungen stapelbasierte WSABUF-Arrays erstellen, auf die der lpBuffers-Parameter verweist.

Überschreiten Sie bei nachrichtenorientierten Sockets nicht die maximale Nachrichtengröße des zugrunde liegenden Anbieters, die durch Abrufen des Werts der Socketoption SO_MAX_MSG_SIZE abgerufen werden kann. Wenn die Daten zu lang sind, um das zugrunde liegende Protokoll atomar zu durchlaufen, wird der Fehler WSAEMSGSIZE zurückgegeben, und es werden keine Daten übertragen.

Windows Me/98/95: Die WSASend-Funktion unterstützt nicht mehr als 16 Puffer.

Hinweis Der erfolgreiche Abschluss einer WSASend bedeutet nicht, dass die Daten erfolgreich übermittelt wurden.
 

Verwenden von dwFlags

Der dwFlags-Parameter kann verwendet werden, um das Verhalten des Funktionsaufrufs über die für den zugeordneten Socket angegebenen Optionen hinaus zu beeinflussen. Das heißt, die Semantik dieser Funktion wird durch die Socketoptionen und den dwFlags-Parameter bestimmt. Letzteres wird mithilfe des bitweisen OR-Operators mit einem der in der folgenden Tabelle aufgeführten Werte erstellt.
Wert Bedeutung
MSG_DONTROUTE Gibt an, dass die Daten nicht dem Routing unterliegen sollen. Ein Windows Sockets-Dienstanbieter kann dieses Flag ignorieren.
MSG_OOB Senden von OOB-Daten an einen Socket im Streamstil, z. B. nur SOCK_STREAM .
MSG_PARTIAL Gibt an, dass lpBuffers nur eine Teilmeldung enthält. Beachten Sie, dass der Fehlercode WSAEOPNOTSUPP von Transporten zurückgegeben wird, die partielle Nachrichtenübertragungen nicht unterstützen.
 
Hinweis Wenn Sie einen blockierenden Winsock-Aufruf wie WSASend ausgeben, bei dem der lpOverlapped-Parameter auf NULL festgelegt ist, muss Winsock möglicherweise auf ein Netzwerkereignis warten, bevor der Aufruf abgeschlossen werden kann. Winsock führt in dieser Situation eine warnbare Wartezeit aus, die durch einen asynchronen Prozeduraufruf (APC) unterbrochen werden kann, der für denselben Thread geplant ist. Das Ausstellen eines weiteren blockierenden Winsock-Aufrufs innerhalb eines APC, der einen fortlaufend blockierenden Winsock-Aufruf im selben Thread unterbrochen hat, führt zu undefiniertem Verhalten und darf niemals von Winsock-Clients versucht werden.
 

Überlappende Socket-E/A

Wenn ein überlappender Vorgang sofort abgeschlossen wird, gibt WSASend den Wert 0 zurück, und der Parameter lpNumberOfBytesSent wird mit der Anzahl der gesendeten Bytes aktualisiert. Wenn der überlappende Vorgang erfolgreich initiiert wurde und später abgeschlossen wird, gibt WSASend SOCKET_ERROR zurück und gibt den Fehlercode WSA_IO_PENDING an. In diesem Fall wird lpNumberOfBytesSent nicht aktualisiert. Wenn der überlappende Vorgang abgeschlossen ist, wird die übertragene Datenmenge entweder über den cbTransferred-Parameter in der Abschlussroutine (sofern angegeben) oder über den lpcbTransfer-Parameter in WSAGetOverlappedResult angegeben.
Hinweis Alle von einem bestimmten Thread initiierten E/A-Vorgänge werden abgebrochen, wenn dieser Thread beendet wird. Bei überlappenden Sockets können ausstehende asynchrone Vorgänge fehlschlagen, wenn der Thread geschlossen wird, bevor die Vorgänge abgeschlossen sind. Weitere Informationen finden Sie unter ExitThread.
 
Die WSASend-Funktion mit überlappender E/A kann innerhalb der Vervollständigungsroutine einer vorherigen WSARecv-, WSARecvFrom-, WSASend- oder WSASendTo-Funktion aufgerufen werden. Dadurch können zeitkritische Datenübertragungen vollständig in einem präemptiven Kontext erfolgen.

Der lpOverlapped-Parameter muss für die Dauer des überlappenden Vorgangs gültig sein. Wenn mehrere E/A-Vorgänge gleichzeitig ausstehen, muss jeder auf eine separate WSAOVERLAPPED-Struktur verweisen.

Wenn der lpCompletionRoutine-ParameterNULL ist, wird der hEvent-Parameter von lpOverlapped signalisiert, wenn der überlappende Vorgang abgeschlossen ist, wenn er ein gültiges Ereignisobjekthandle enthält. Eine Anwendung kann WSAWaitForMultipleEvents oder WSAGetOverlappedResult verwenden, um auf das Ereignisobjekt zu warten oder abzufragen.

Wenn lpCompletionRoutine nicht NULL ist, wird der hEvent-Parameter ignoriert und kann von der Anwendung verwendet werden, um Kontextinformationen an die Vervollständigungsroutine zu übergeben. Ein Aufrufer, der eine lpCompletionRoutine ungleich NULL übergibt und später WSAGetOverlappedResult für dieselbe überlappende E/A-Anforderung aufruft, legt den fWait-Parameter für diesen Aufruf von WSAGetOverlappedResult möglicherweise nicht auf TRUE fest. In diesem Fall ist die Verwendung des hEvent-Parameters nicht definiert, und der Versuch, auf den hEvent-Parameter zu warten, würde zu unvorhersehbaren Ergebnissen führen.

Die Vervollständigungsroutine folgt den gleichen Regeln wie für Windows-Datei-E/A-Vervollständigungsroutinen. Die Vervollständigungsroutine wird erst aufgerufen, wenn sich der Thread in einem warnbaren Wartezustand befindet, z. B. wenn die Funktion WSAWaitForMultipleEvents mit dem fAlertable-Parameter auf TRUE aufgerufen wird.

Die Transportanbieter ermöglichen einer Anwendung das Aufrufen von Sende- und Empfangsvorgängen aus dem Kontext der Socket-E/A-Vervollständigungsroutine und garantieren, dass E/A-Vervollständigungsroutinen für einen bestimmten Socket nicht geschachtelt werden. Dadurch können zeitkritische Datenübertragungen vollständig in einem präemptiven Kontext erfolgen.

Das folgende C++-Codebeispiel ist ein Prototyp der Vervollständigungsroutine.


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

Die CompletionRoutine-Funktion ist ein Platzhalter für einen anwendungsdefinierte oder bibliotheksdefinierte Funktionsnamen. Der dwError-Parameter gibt den Abschluss status für den überlappenden Vorgang an, wie durch lpOverlapped angegeben. cbTransferred gibt die Anzahl der gesendeten Bytes an. Derzeit sind keine Flagwerte definiert, und dwFlags ist 0 (null). Diese Funktion gibt keinen Wert zurück.

Die Rückgabe von dieser Funktion ermöglicht den Aufruf einer weiteren ausstehenden Vervollständigungsroutine für diesen Socket. Alle wartenden Vervollständigungsroutinen werden aufgerufen, bevor die Wartedauer des warnfähigen Threads mit einem Rückgabecode von WSA_IO_COMPLETION erfüllt wird. Die Vervollständigungsroutinen können in beliebiger Reihenfolge aufgerufen werden, nicht unbedingt in derselben Reihenfolge, in der die überlappenden Vorgänge abgeschlossen werden. Die bereitgestellten Puffer werden jedoch garantiert in derselben Reihenfolge gesendet, in der sie angegeben sind.

Die Reihenfolge der Aufrufe an WSASend ist auch die Reihenfolge, in der die Puffer an die Transportschicht übertragen werden. WSASend sollte nicht gleichzeitig für denselben streamorientierten Socket aus verschiedenen Threads aufgerufen werden, da einige Winsock-Anbieter eine große Sendeanforderung in mehrere Übertragungen aufteilen können. Dies kann dazu führen, dass unbeabsichtigte Daten von mehreren gleichzeitigen Sendeanforderungen auf demselben streamorientierten Socket überlappen.

Beispielcode

Im folgenden Codebeispiel wird veranschaulicht, wie die WSASend-Funktion im überlappenden E/A-Modus verwendet wird.
#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: Diese Funktion wird für Windows Phone Store-Apps ab Windows Phone 8 unterstützt.

Windows 8.1 und Windows Server 2012 R2: Diese Funktion wird für Windows Store-Apps auf Windows 8.1, Windows Server 2012 R2 und höher unterstützt.

Anforderungen

Anforderung Wert
Unterstützte Mindestversion (Client) Windows 8.1, Windows Vista [Desktop-Apps | UWP-Apps]
Unterstützte Mindestversion (Server) Windows Server 2003 [Desktop-Apps | UWP-Apps]
Zielplattform Windows
Kopfzeile winsock2.h
Bibliothek Ws2_32.lib
DLL Ws2_32.dll

Weitere Informationen

WSABUF

WSACloseEvent

WSAConnect

WSACreateEvent

WSAGetOverlappedResult

WSAOVERLAPPED

WSASocket

WSAWaitForMultipleEvents

Winsock-Funktionen

Winsock-Referenz

connect

send

Socket