WSARecv-Funktion (winsock2.h)

Die WSARecv-Funktion empfängt Daten von einem verbundenen Socket oder einem gebundenen verbindungslosen Socket.

Syntax

int WSAAPI WSARecv(
  [in]      SOCKET                             s,
  [in, out] LPWSABUF                           lpBuffers,
  [in]      DWORD                              dwBufferCount,
  [out]     LPDWORD                            lpNumberOfBytesRecvd,
  [in, out] LPDWORD                            lpFlags,
  [in]      LPWSAOVERLAPPED                    lpOverlapped,
  [in]      LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

Parameter

[in] s

Ein Deskriptor, der einen verbundenen Socket identifiziert.

[in, out] 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.

[in] dwBufferCount

Die Anzahl der WSABUF-Strukturen im lpBuffers-Array .

[out] lpNumberOfBytesRecvd

Ein Zeiger auf die Anzahl der von diesem Aufruf empfangenen Daten in Bytes, wenn der Empfangsvorgang 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, out] lpFlags

Ein Zeiger auf Flags, die zum Ändern des Verhaltens des WSARecv-Funktionsaufrufs verwendet werden. Weitere Informationen finden Sie im Abschnitt mit Hinweisen.

[in] lpOverlapped

Ein Zeiger auf eine WSAOVERLAPPED-Struktur (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 Empfangsvorgang abgeschlossen wurde (wird bei nicht überlappten Sockets ignoriert).

Rückgabewert

Wenn kein Fehler auftritt und der Empfangsvorgang sofort abgeschlossen wurde, gibt WSARecv 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 der Abschluss zu einem späteren Zeitpunkt angezeigt wird. Ein anderer Fehlercode gibt an, dass der überlappende Vorgang nicht erfolgreich initiiert wurde und keine Abschlussanzeige angezeigt wird.

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.
WSAEDISCON
Sockets ist nachrichtenorientiert, und die virtuelle Verbindung wurde von der Remoteseite ordnungsgemäß geschlossen.
WSAEFAULT
Der lpBuffers-Parameter ist nicht vollständig in einem gültigen Teil des Benutzeradressraums enthalten.
WSAEINPROGRESS
Ein blockierter Windows Sockets 1.1-Aufruf wird ausgeführt, oder der Dienstanbieter verarbeitet noch eine Rückruffunktion.
WSAEINTR
Der (blockierende) Aufruf wurde von der WSACancelBlockingCall-Funktion abgebrochen.
WSAEINVAL
Der Socket wurde nicht gebunden (z. B. mit bindung).
WSAEMSGSIZE
Die Nachricht war zu groß, um in den angegebenen Puffer zu passen, und (nur für unzuverlässige Protokolle) wurde jeder nachfolgende Teil der Nachricht verworfen, der nicht in den Puffer passte.
WSAENETDOWN
Fehler beim Netzwerksubsystem.
WSAENETRESET
Bei einem verbindungsorientierten Socket gibt dieser Fehler an, dass die Verbindung aufgrund einer Keep-Alive-Aktivität unterbrochen wurde, die während des Vorgangs einen Fehler erkannt hat. Für einen Datagrammsocket zeigt dieser Fehler an, dass die Gültigkeitsdauer abgelaufen ist.
WSAENOTCONN
Der Socket ist nicht verbunden.
WSAENOTSOCK
Der Deskriptor ist kein Socket.
WSAEOPNOTSUPP
MSG_OOB angegeben wurde, aber der Socket nicht im Streamstil wie typ SOCK_STREAM, werden OOB-Daten in der diesem Socket zugeordneten Kommunikationsdomäne nicht unterstützt, oder der Socket ist unidirektional und unterstützt nur Sendevorgänge.
WSAESHUTDOWN
Die Steckdose wurde heruntergefahren; Es ist nicht möglich, WSARecv für einen Socket aufzurufen, nachdem das Herunterfahren aufgerufen wurde, wobei auf SD_RECEIVE oder SD_BOTH festgelegt ist.
WSAETIMEDOUT
Netzwerkfehler oder Antwortfehler des Peersystems. Die Verbindung wurde abgebrochen.
WSAEWOULDBLOCK

Windows NT: Überlappende Sockets: Es gibt zu viele ausstehende überlappende E/A-Anforderungen. Nicht überlappende Sockets: Der Socket ist als nicht blockiert gekennzeichnet, und der Empfangsvorgang 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 initiiert, und der Abschluss wird zu einem späteren Zeitpunkt angezeigt.
WSA_OPERATION_ABORTED
Der überlappende Vorgang wurde aufgrund des Schließens des Sockets abgebrochen.

Hinweise

Die WSARecv-Funktion bietet im Vergleich zur Recv-Standardfunktion einige zusätzliche Features in drei wichtigen Bereichen:

  • Es kann in Verbindung mit überlappenden Sockets verwendet werden, um überlappende Recv-Vorgänge auszuführen.
  • Dadurch können mehrere Empfangspuffer angegeben werden, sodass sie auf den Punkt-/Gather-Typ von E/A anwendbar sind.
  • Der lpFlags-Parameter wird sowohl bei der Eingabe als auch bei der Ausgabe verwendet, sodass Anwendungen den Ausgabezustand des MSG_PARTIAL Flagbits erkennen können. Das MSG_PARTIAL Flagbit wird jedoch nicht von allen Protokollen unterstützt.
Die WSARecv-Funktion wird für verbundene Sockets oder gebundene verbindungslose Sockets verwendet, die vom s-Parameter angegeben werden, und wird zum Lesen eingehender Daten verwendet. Die lokale Adresse des Sockets muss bekannt sein. Bei Serveranwendungen erfolgt dies in der Regel explizit über bind oder implizit über accept oder WSAAccept. Von einer expliziten Bindung für Clientanwendungen wird abgeraten. Bei Clientanwendungen kann der Socket implizit über connect, WSAConnect, sendto, WSASendTo oder WSAJoinLeaf an eine lokale Adresse gebunden werden.

Bei verbundenen, verbindungslosen Sockets schränkt diese Funktion die Adressen ein, von denen empfangene Nachrichten akzeptiert werden. Die Funktion gibt nur Nachrichten von der in der Verbindung angegebenen Remoteadresse zurück. Nachrichten von anderen Adressen werden (automatisch) verworfen.

Für überlappende Sockets wird WSARecv verwendet, um einen oder mehrere Puffer zu posten, in denen eingehende Daten platziert werden, sobald sie verfügbar werden, worauf die anwendungsspezifische Vervollständigungsanzeige (Aufruf der Vervollständigungsroutine oder Einstellung eines Ereignisobjekts) erfolgt. Wenn der Vorgang nicht sofort abgeschlossen wird, wird der endgültige Abschluss status über die Abschlussroutine oder WSAGetOverlappedResult abgerufen.

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 .
 
Wenn sowohl lpOverlapped als auch lpCompletionRoutineNULL sind, wird der Socket in dieser Funktion als nicht überlappter Socket behandelt.

Bei nicht überlappten Sockets ist die blockierende Semantik mit der der recv-Standardfunktion identisch, und die Parameter lpOverlapped und lpCompletionRoutine werden ignoriert. Alle Daten, die bereits vom Transport empfangen und gepuffert wurden, werden in die angegebenen Benutzerpuffer kopiert. Im Fall eines blockierenden Sockets, bei dem derzeit keine Daten empfangen und vom Transport gepuffert wurden, wird der Aufruf blockiert, bis Daten empfangen werden. Windows Sockets 2 definiert keinen standardmäßigen Blockierungstimeoutmechanismus für diese Funktion. Bei Protokollen, die als Bytestreamprotokolle fungieren, versucht der Stapel, so viele Daten wie möglich zurückzugeben, abhängig vom verfügbaren Pufferspeicherplatz und der menge der empfangenen Daten, die verfügbar sind. Der Empfang eines einzelnen Byte reicht jedoch aus, um die Blockierung des Aufrufers aufzuheben. Es gibt keine Garantie, dass mehr als ein einzelnes Byte zurückgegeben wird. Für Protokolle, die als nachrichtenorientiert fungieren, ist eine vollständige Nachricht erforderlich, um die Blockierung des Aufrufers aufzuheben.

Hinweis Die Socketoptionen SO_RCVTIMEO und SO_SNDTIMEO nur für blockierende Sockets gelten.
 
Ob ein Protokoll als Bytedatenstrom fungiert, wird durch die Einstellung von XP1_MESSAGE_ORIENTED und XP1_PSEUDO_STREAM in seiner WSAPROTOCOL_INFO-Struktur und der Einstellung des MSG_PARTIAL-Flags bestimmt, das an diese Funktion übergeben wird (für Protokolle, die dies unterstützen). In der folgenden Tabelle sind relevante Kombinationen aufgeführt (ein Sternchen (*) gibt an, dass die Einstellung dieses Bits in diesem Fall keine Rolle spielt).
XP1_MESSAGE_ORIENTED XP1_PSEUDO_STREAM MSG_PARTIAL Fungiert als
nicht festgelegt * * Bytedatenstrom
* Set * Bytedatenstrom
set Nicht festgelegt set Bytedatenstrom
set Nicht festgelegt nicht festgelegt Nachrichtenorientiert
 

Die Puffer werden in der Reihenfolge gefüllt, in der sie im Array angezeigt werden, auf das von lpBuffers verwiesen wird, und die Puffer werden gepackt, sodass keine Löcher entstehen.

Wenn diese Funktion auf überlappende Weise ausgeführt wird, liegt es in der Verantwortung des Winsock-Dienstanbieters, die WSABUF-Strukturen zu erfassen, bevor sie von diesem Aufruf zurückgegeben wird. Dadurch können Anwendungen stapelbasierte WSABUF-Arrays erstellen, auf die der lpBuffers-Parameter verweist.

Bei Bytestreamsockets (z. B. Typ SOCK_STREAM) werden eingehende Daten in die Puffer platziert, bis die Puffer gefüllt, die Verbindung geschlossen oder die intern gepufferten Daten erschöpft sind. Unabhängig davon, ob die eingehenden Daten alle Puffer füllen, tritt die Vervollständigungsanzeige für überlappende Sockets auf.

Für nachrichtenorientierte Sockets (z. B. Typ SOCK_DGRAM) wird eine eingehende Nachricht in die Puffer bis zur Gesamtgröße der Puffer platziert, und die Abschlussanzeige tritt für überlappende Sockets auf. Wenn die Nachricht größer als die Puffer ist, werden die Puffer mit dem ersten Teil der Nachricht gefüllt. Wenn das MSG_PARTIAL-Feature vom zugrunde liegenden Dienstanbieter unterstützt wird, wird das MSG_PARTIAL-Flag in lpFlags festgelegt, und nachfolgende Empfangsvorgänge rufen den Rest der Nachricht ab. Wenn MSG_PARTIAL nicht unterstützt wird, aber das Protokoll zuverlässig ist, generiert WSARecv den Fehler WSAEMSGSIZE , und ein nachfolgender Empfangsvorgang mit einem größeren Puffer kann verwendet werden, um die gesamte Nachricht abzurufen. Andernfalls (das Protokoll ist unzuverlässig und unterstützt MSG_PARTIAL nicht) geht die überschüssigen Daten verloren, und WSARecv generiert den Fehler WSAEMSGSIZE.

Bei verbindungsorientierten Sockets kann WSARecv die ordnungsgemäße Beendigung der virtuellen Verbindung auf eine von zwei Arten angeben, die davon abhängen, ob der Socket bytestream- oder nachrichtenorientiert ist. Bei Bytestreams bedeutet null gelesene Bytes (wie durch einen Null-Rückgabewert angegeben, um den Erfolg anzuzeigen, und lpNumberOfBytesRecvd-Wert von 0) einen ordnungsgemäßen Abschluss und dass keine Bytes mehr gelesen werden. Für nachrichtenorientierte Sockets, bei denen eine Null-Byte-Nachricht häufig zulässig ist, wird ein Fehler mit dem Fehlercode WSAEDISCON verwendet, um einen ordnungsgemäßen Abschluss anzuzeigen. In jedem Fall gibt ein Rückgabefehlercode von WSAECONNRESET an, dass ein abgebrochener Abschluss aufgetreten ist.

Der lpFlags-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 lpFlags-Parameter bestimmt. Letzteres wird mithilfe des bitweisen OR-Operators mit einem der in der folgenden Tabelle aufgeführten Werte erstellt.

Wert Bedeutung
MSG_PEEK Hier werden die eingehenden Daten angezeigt. Die Daten werden in den Puffer kopiert, aber nicht aus der Eingabewarteschlange entfernt.

Dieses Flag ist nur für nicht überlappte Sockets gültig.

MSG_OOB Verarbeitet OOB-Daten.
MSG_PARTIAL Dieses Flag gilt nur für nachrichtenorientierte Sockets. Bei der Ausgabe gibt dieses Flag an, dass die angegebenen Daten ein Teil der nachricht sind, die vom Absender übertragen wird. Die verbleibenden Teile der Nachricht werden in nachfolgenden Empfangsvorgängen angegeben. Ein nachfolgender Empfangsvorgang mit deaktiviertem MSG_PARTIAL Flag gibt das Ende der Nachricht des Absenders an.

Als Eingabeparameter gibt dieses Flag an, dass der Empfangsvorgang auch dann abgeschlossen werden soll, wenn nur ein Teil einer Nachricht vom Transportanbieter empfangen wurde.

MSG_PUSH_IMMEDIATE Dieses Flag gilt nur für streamorientierte Sockets. Dieses Flag ermöglicht es einer Anwendung, die Streamsockets verwendet, den Transportanbieter anweisen, den Abschluss teilweise gefüllter ausstehender Empfangsanforderungen nicht zu verzögern. Dies ist ein Hinweis an den Transportanbieter, dass die Anwendung bereit ist, eingehende Daten so schnell wie möglich zu empfangen, ohne unbedingt auf den Rest der Daten zu warten, die sich möglicherweise noch in der Übertragung befinden. Was eine teilweise ausgefüllte, ausstehende Empfangsanforderung darstellt, ist eine transportspezifische Angelegenheit.

Im Fall von TCP bezieht sich dies auf den Fall, dass eingehende TCP-Segmente in den Datenpuffer der Empfangsanforderung eingefügt werden, wobei keines der TCP-Segmente den PUSH-Bitwert 1 angibt. In diesem Fall kann TCP die teilweise ausgefüllte Empfangsanforderung etwas länger enthalten, damit der Rest der Daten mit einem TCP-Segment eingehen kann, in dem das PUSH-Bit auf 1 festgelegt ist. Dieses Flag weist TCP an, die Empfangsanforderung nicht zu halten, sondern sofort abzuschließen.

Die Verwendung dieses Flags für große Blockübertragungen wird nicht empfohlen, da die Verarbeitung von Teilblöcken häufig nicht optimal ist. Dieses Flag ist nur für Fälle nützlich, in denen der Empfang und die Verarbeitung der Teildaten sofort dazu beiträgt, die Verarbeitungslatenz zu verringern.

Dieses Flag ist eher ein Hinweis als eine tatsächliche Garantie.

Dieses Flag wird unter Windows 8.1, Windows Server 2012 R2 und höher unterstützt.

MSG_WAITALL Die Empfangsanforderung wird nur abgeschlossen, wenn eines der folgenden Ereignisse auftritt:
  • Der vom Aufrufer bereitgestellte Puffer ist vollständig voll.
  • Die Verbindung wurde geschlossen.
  • Die Anforderung wurde abgebrochen, oder es ist ein Fehler aufgetreten.

Beachten Sie, dass dieser Aufruf mit WSAEOPNOTSUPP fehlschlägt, wenn der zugrunde liegende Transportanbieter MSG_WAITALL nicht unterstützt oder sich der Socket in einem nicht blockierenden Modus befindet. Wenn MSG_WAITALL zusammen mit MSG_OOB, MSG_PEEK oder MSG_PARTIAL angegeben wird, schlägt dieser Aufruf mit WSAEOPNOTSUPP fehl.

Dieses Flag wird für Datagrammsockets oder nachrichtenorientierte Sockets nicht unterstützt.

 

Bei nachrichtenorientierten Sockets wird das MSG_PARTIAL Bit im lpFlags-Parameter festgelegt, wenn eine Teilnachricht empfangen wird. Wenn eine vollständige Nachricht empfangen wird, wird MSG_PARTIAL in lpFlags gelöscht. Bei verzögerter Fertigstellung wird der Wert, auf den lpFlags verweist, nicht aktualisiert. Wenn der Abschluss angegeben wurde, sollte die Anwendung WSAGetOverlappedResult aufrufen und die durch den lpdwFlags-Parameter angegebenen Flags untersuchen.

Hinweis Wenn Sie einen blockierenden Winsock-Aufruf wie WSARecv 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 WSARecv den Wert 0 (null) zurück, und der Parameter lpNumberOfBytesRecvd wird mit der Anzahl der empfangenen Bytes aktualisiert, und die vom lpFlags-Parameter angegebenen Flagbits werden ebenfalls aktualisiert. Wenn der überlappende Vorgang erfolgreich initiiert wurde und später abgeschlossen wird, gibt WSARecvSOCKET_ERROR zurück und gibt den Fehlercode WSA_IO_PENDING an. In diesem Fall werden lpNumberOfBytesRecvd und lpFlags 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. Flagwerte werden abgerufen, indem der lpdwFlags-Parameter von WSAGetOverlappedResult untersucht wird.

Die WSARecv-Funktion mit überlappenden E/A kann innerhalb der Vervollständigungsroutine einer früheren WSARecv-, WSARecvFrom-, WSASend- oder WSASendTo-Funktion aufgerufen werden. Für einen bestimmten Socket werden E/A-Abschlussroutinen nicht geschachtelt. 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.

Der Prototyp der Vervollständigungsroutine sieht wie folgt aus:


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

CompletionRoutine ist ein Platzhalter für einen anwendungsdefinierte oder bibliotheksdefinierte Funktionsnamen. DwError gibt den Abschluss status für den überlappenden Vorgang an, wie durch lpOverlapped angegeben. Der cbTransferred-Parameter gibt die Anzahl der empfangenen Bytes an. Der dwFlags-Parameter enthält Informationen, die in lpFlags angezeigt worden wären, wenn der Empfangsvorgang sofort abgeschlossen worden wäre. 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. Bei Verwendung von WSAWaitForMultipleEvents werden alle Wartevervollständigungsroutinen aufgerufen, bevor die Wartezeit des warnbaren Threads mit einem Rückgabecode WSA_IO_COMPLETION. Die Vervollständigungsroutinen können in beliebiger Reihenfolge aufgerufen werden, nicht unbedingt in der gleichen Reihenfolge, in der die überlappenden Vorgänge abgeschlossen werden. Die gebuchten Puffer werden jedoch garantiert in derselben Reihenfolge ausgefüllt, in der sie angegeben werden.

Wenn Sie E/A-Vervollständigungsports verwenden, beachten Sie, dass die Reihenfolge der Aufrufe an WSARecv auch die Reihenfolge ist, in der die Puffer aufgefüllt werden. WSARecv sollte nicht auf demselben Socket gleichzeitig von verschiedenen Threads aufgerufen werden, da dies zu einer unvorhersehbaren Pufferreihenfolge führen kann.

Beispielcode

Im folgenden Beispiel wird gezeigt, wie die WSARecv-Funktion im überlappenden E/A-Modus verwendet wird.
#ifndef UNICODE
#define UNICODE
#endif

#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")

#pragma warning(disable: 4127)  // Conditional expression is a constant

#define DATA_BUFSIZE 4096

int __cdecl main(int argc, char **argv)
{
    WSADATA wsd;
    struct addrinfo *result = NULL, *ptr = NULL, hints;
    WSAOVERLAPPED RecvOverlapped;
    SOCKET ConnSocket = INVALID_SOCKET;
    WSABUF DataBuf;
    DWORD RecvBytes, Flags;
    char buffer[DATA_BUFSIZE];

    int err = 0;
    int rc;

    if (argc != 2) {
        wprintf(L"usage: %s server-name\n", argv[0]);
        return 1;
    }
    // Load Winsock
    rc = WSAStartup(MAKEWORD(2, 2), &wsd);
    if (rc != 0) {
        wprintf(L"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 retrieve the server address for IPv4
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    rc = getaddrinfo(argv[1], "27015", &hints, &result);
    if (rc != 0) {
        wprintf(L"getaddrinfo failed with error: %d\n", rc);
        return 1;
    }

    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {

        ConnSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (ConnSocket == INVALID_SOCKET) {
            wprintf(L"socket failed with error: %d\n", WSAGetLastError());
            freeaddrinfo(result);
            return 1;
        }

        rc = connect(ConnSocket, ptr->ai_addr, (int) ptr->ai_addrlen);
        if (rc == SOCKET_ERROR) {

            if (WSAECONNREFUSED == (err = WSAGetLastError())) {
                closesocket(ConnSocket);
                ConnSocket = INVALID_SOCKET;
                continue;
            }
            wprintf(L"connect failed with error: %d\n", err);
            freeaddrinfo(result);
            closesocket(ConnSocket);
            return 1;
        }
        break;
    }
    if (ConnSocket == INVALID_SOCKET) {
        wprintf(L"Unable to establish connection with the server!\n");
        freeaddrinfo(result);
        return 1;
    }

    wprintf(L"Client connected...\n");

    // Make sure the RecvOverlapped struct is zeroed out
    SecureZeroMemory((PVOID) & RecvOverlapped, sizeof (WSAOVERLAPPED));

    // Create an event handle and setup an overlapped structure.
    RecvOverlapped.hEvent = WSACreateEvent();
    if (RecvOverlapped.hEvent == NULL) {
        wprintf(L"WSACreateEvent failed: %d\n", WSAGetLastError());
        freeaddrinfo(result);
        closesocket(ConnSocket);
        return 1;
    }

    DataBuf.len = DATA_BUFSIZE;
    DataBuf.buf = buffer;

    // Call WSARecv until the peer closes the connection
    // or until an error occurs
    while (1) {

        Flags = 0;
        rc = WSARecv(ConnSocket, &DataBuf, 1, &RecvBytes, &Flags, &RecvOverlapped, NULL);
        if ((rc == SOCKET_ERROR) && (WSA_IO_PENDING != (err = WSAGetLastError()))) {
            wprintf(L"WSARecv failed with error: %d\n", err);
            break;
        }

        rc = WSAWaitForMultipleEvents(1, &RecvOverlapped.hEvent, TRUE, INFINITE, TRUE);
        if (rc == WSA_WAIT_FAILED) {
            wprintf(L"WSAWaitForMultipleEvents failed with error: %d\n", WSAGetLastError());
            break;
        }

        rc = WSAGetOverlappedResult(ConnSocket, &RecvOverlapped, &RecvBytes, FALSE, &Flags);
        if (rc == FALSE) {
            wprintf(L"WSARecv operation failed with error: %d\n", WSAGetLastError());
            break;
        }

        wprintf(L"Read %d bytes\n", RecvBytes);

        WSAResetEvent(RecvOverlapped.hEvent);

        // If 0 bytes are received, the connection was closed
        if (RecvBytes == 0)
            break;
    }

    WSACloseEvent(RecvOverlapped.hEvent);
    closesocket(ConnSocket);
    freeaddrinfo(result);

    WSACleanup();

    return 0;
}


Windows Phone 8: Diese Funktion wird für Windows Phone Store-Apps auf Windows Phone 8 und höher unterstützt.

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

Anforderungen

   
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

WSACreateEvent

WSAGetOverlappedResult

WSAOVERLAPED

WSASocket

WSAWaitForMultipleEvents

Winsock-Funktionen

Winsock-Referenz

Recv