Partager via


Fonction WSARecv (winsock2.h)

La fonction WSARecv reçoit des données d’un socket connecté ou d’un socket sans connexion lié.

Syntaxe

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

Paramètres

[in] s

Descripteur identifiant un socket connecté.

[in, out] lpBuffers

Pointeur vers un tableau de structures WSABUF . Chaque structure WSABUF contient un pointeur vers une mémoire tampon et la longueur, en octets, de la mémoire tampon.

[in] dwBufferCount

Nombre de structures WSABUF dans le tableau lpBuffers .

[out] lpNumberOfBytesRecvd

Pointeur vers le nombre, en octets, de données reçues par cet appel si l’opération de réception se termine immédiatement.

Utilisez NULL pour ce paramètre si le paramètre lpOverlapped n’est pas NULL pour éviter des résultats potentiellement erronés. Ce paramètre ne peut être NULL que si le paramètre lpOverlapped n’est pas NULL.

[in, out] lpFlags

Pointeur vers les indicateurs utilisés pour modifier le comportement de l’appel de fonction WSARecv . Pour plus d'informations, consultez la section Notes.

[in] lpOverlapped

Pointeur vers une structure WSAOVERLAPPED (ignoré pour les sockets non survolés).

[in] lpCompletionRoutine

Type : _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE

Pointeur vers la routine d’achèvement appelée lorsque l’opération de réception a été terminée (ignoré pour les sockets non survolés).

Valeur retournée

Si aucune erreur ne se produit et que l’opération de réception est terminée immédiatement, WSARecv retourne zéro. Dans ce cas, la routine d’achèvement a déjà été planifiée pour être appelée une fois que le thread appelant est à l’état alertable. Sinon, une valeur de SOCKET_ERROR est retournée et un code d’erreur spécifique peut être récupéré en appelant WSAGetLastError. Le code d’erreur WSA_IO_PENDING indique que l’opération qui se chevauche a été lancée avec succès et que l’achèvement sera indiqué ultérieurement. Tout autre code d’erreur indique que l’opération qui se chevauche n’a pas été lancée avec succès et qu’aucune indication d’achèvement ne se produira.

Code d'erreur Signification
WSAECONNABORTED
Le circuit virtuel a été interrompu en raison d'un délai d'attente ou d'un autre échec.
WSAECONNRESET
Pour un socket de flux, le circuit virtuel a été réinitialisé par le côté distant. L’application doit fermer le socket, car il n’est plus utilisable. Pour un socket de datagramme UDP, cette erreur indique qu’une opération d’envoi précédente a entraîné un message ICMP « Port inaccessible ».
WSAEDISCON
Le socket s est orienté message et le circuit virtuel a été correctement fermé par le côté distant.
WSAEFAULT
Le paramètre lpBuffers n’est pas entièrement contenu dans une partie valide de l’espace d’adressage utilisateur.
WSAEINPROGRESS
Un appel bloquant Windows Sockets 1.1 est en cours ou le fournisseur de services traite toujours une fonction de rappel.
WSAEINTR
L’appel (bloquant) a été annulé par la fonction WSACancelBlockingCall .
WSAEINVAL
Le socket n’a pas été lié (par exemple, avec liaison).
WSAEMSGSIZE
Le message était trop volumineux pour tenir dans la mémoire tampon spécifiée et (pour les protocoles non fiables uniquement) toute partie de fin du message qui ne correspondait pas à la mémoire tampon a été ignorée.
WSAENETDOWN
Le sous-système réseau a échoué.
WSAENETRESET
Pour un socket orienté connexion, cette erreur indique que la connexion a été interrompue en raison d’une activité de maintien en vie qui a détecté une défaillance pendant que l’opération était en cours. Pour un socket datagramme, cette erreur indique que la durée de vie (TTL, Time to Live) a expiré.
WSAENOTCONN
Le socket n'est pas connecté.
WSAENOTSOCK
Le descripteur n’est pas un socket.
WSAEOPNOTSUPP
MSG_OOB a été spécifié, mais le socket n’est pas de type flux tel que le type SOCK_STREAM, les données OOB ne sont pas prises en charge dans le domaine de communication associé à ce socket, ou le socket est unidirectionnel et prend uniquement en charge les opérations d’envoi.
WSAESHUTDOWN
Le socket a été arrêté ; il n’est pas possible d’appeler WSARecv sur un socket après l’appel de l’arrêt avec la valeurdéfinie sur SD_RECEIVE ou SD_BOTH.
WSAETIMEDOUT
La connexion a été supprimée en raison d'un échec réseau ou d'un échec de réponse du système homologue.
WSAEWOULDBLOCK

Windows NT : Sockets superposés : il y a trop de demandes d’E/S qui se chevauchent. Sockets non bloqués : le socket est marqué comme non bloquant et l’opération de réception ne peut pas être effectuée immédiatement.

WSANOTINITIALISED
Un appel WSAStartup réussi doit se produire avant d’utiliser cette fonction.
WSA_IO_PENDING
Une opération qui se chevauche a été lancée avec succès et l’achèvement sera indiqué ultérieurement.
WSA_OPERATION_ABORTED
L’opération qui se chevauche a été annulée en raison de la fermeture du socket.

Remarques

La fonction WSARecv fournit des fonctionnalités supplémentaires par rapport à la fonction recv standard dans trois domaines importants :

  • Il peut être utilisé conjointement avec des sockets qui se chevauchent pour effectuer des opérations recv qui se chevauchent.
  • Il permet de spécifier plusieurs mémoires tampons de réception, ce qui le rend applicable au type scatter/collect d’E/S.
  • Le paramètre lpFlags est utilisé à la fois en entrée et retourné en sortie, ce qui permet aux applications de détecter l’état de sortie du bit d’indicateur MSG_PARTIAL . Toutefois, le bit d’indicateur MSG_PARTIAL n’est pas pris en charge par tous les protocoles.
La fonction WSARecv est utilisée sur les sockets connectés ou les sockets sans connexion liés spécifiés par le paramètre s et est utilisée pour lire les données entrantes. L’adresse locale du socket doit être connue. Pour les applications serveur, cela se fait généralement explicitement par le biais d’une liaison ou implicitement via accept ou WSAAccept. La liaison explicite est déconseillée pour les applications clientes. Pour les applications clientes, le socket peut devenir implicitement lié à une adresse locale via connect, WSAConnect, sendto, WSASendTo ou WSAJoinLeaf.

Pour les sockets connectés sans connexion, cette fonction limite les adresses à partir desquelles les messages reçus sont acceptés. La fonction retourne uniquement les messages de l’adresse distante spécifiée dans la connexion. Les messages provenant d’autres adresses sont (en mode silencieux) ignorés.

Pour les sockets qui se chevauchent, WSARecv est utilisé pour publier une ou plusieurs mémoires tampons dans lesquelles les données entrantes seront placées dès qu’elles seront disponibles, après quoi l’indication d’achèvement spécifiée par l’application (appel de la routine d’achèvement ou du paramètre d’un objet d’événement) se produit. Si l’opération ne se termine pas immédiatement, la status d’achèvement finale est récupérée via la routine d’achèvement ou WSAGetOverlappedResult.

Note Toutes les E/S initiées par un thread donné sont annulées à la sortie de ce thread. Pour les sockets qui se chevauchent, les opérations asynchrones en attente peuvent échouer si le thread est fermé avant la fin des opérations. Pour plus d’informations, consultez ExitThread .
 
Si lpOverlapped et lpCompletionRoutine ont la valeur NULL, le socket dans cette fonction sera traité comme un socket nonoverlapped.

Pour les sockets non obstrués, la sémantique de blocage est identique à celle de la fonction recv standard et les paramètres lpOverlapped et lpCompletionRoutine sont ignorés. Toutes les données qui ont déjà été reçues et mises en mémoire tampon par le transport seront copiées dans les mémoires tampons utilisateur spécifiées. Dans le cas d’un socket bloquant sans qu’aucune donnée n’ait été reçue et mise en mémoire tampon par le transport, l’appel est bloqué jusqu’à ce que les données soient reçues. Windows Sockets 2 ne définit aucun mécanisme de délai de blocage standard pour cette fonction. Pour les protocoles agissant comme des protocoles de flux d’octets, la pile tente de retourner autant de données que possible sous réserve de l’espace tampon disponible et de la quantité de données reçues disponibles. Toutefois, la réception d’un seul octet est suffisante pour débloquer l’appelant. Il n’existe aucune garantie que plusieurs octets seront retournés. Pour les protocoles orientés message, un message complet est nécessaire pour débloquer l’appelant.

Note Les options de socket SO_RCVTIMEO et SO_SNDTIMEO s’appliquent uniquement aux sockets bloquants.
 
Le fait qu’un protocole agisse ou non en tant que flux d’octets est déterminé par le paramètre de XP1_MESSAGE_ORIENTED et de XP1_PSEUDO_STREAM dans sa structure WSAPROTOCOL_INFO et par le paramètre de l’indicateur MSG_PARTIAL passé à cette fonction (pour les protocoles qui la prennent en charge). Le tableau suivant répertorie les combinaisons pertinentes (un astérisque (*) indique que le paramètre de ce bit n’a pas d’importance dans ce cas).
XP1_MESSAGE_ORIENTED XP1_PSEUDO_STREAM MSG_PARTIAL Agit en tant que
non défini * * Flux d’octets
* Définissez * Flux d’octets
set Non défini set Flux d’octets
set Non défini non défini Orienté message
 

Les mémoires tampons sont remplies dans l’ordre dans lequel elles apparaissent dans le tableau pointé par lpBuffers, et les mémoires tampons sont emballées afin qu’aucun trou ne soit créé.

Si cette fonction se chevauche, il incombe au fournisseur de services Winsock de capturer les structures WSABUF avant de revenir de cet appel. Cela permet aux applications de créer des tableaux WSABUF basés sur une pile pointés par le paramètre lpBuffers .

Pour les sockets de type flux d’octets (par exemple, le type SOCK_STREAM), les données entrantes sont placées dans les mémoires tampons jusqu’à ce que les mémoires tampons soient remplies, que la connexion soit fermée ou que les données mises en mémoire tampon interne soient épuisées. Que les données entrantes remplissent ou non toutes les mémoires tampons, l’indication d’achèvement se produit pour les sockets qui se chevauchent.

Pour les sockets orientés message (par exemple, le type SOCK_DGRAM), un message entrant est placé dans les mémoires tampons jusqu’à la taille totale des mémoires tampons, et l’indication d’achèvement se produit pour les sockets qui se chevauchent. Si le message est plus grand que les mémoires tampons, les mémoires tampons sont remplies avec la première partie du message. Si la fonctionnalité de MSG_PARTIAL est prise en charge par le fournisseur de services sous-jacent, l’indicateur MSG_PARTIAL est défini dans lpFlags et les opérations de réception suivantes récupèrent le reste du message. Si MSG_PARTIAL n’est pas pris en charge mais que le protocole est fiable, WSARecv génère l’erreur WSAEMSGSIZE et une opération de réception ultérieure avec une mémoire tampon plus grande peut être utilisée pour récupérer l’intégralité du message. Sinon, (autrement dit, le protocole n’est pas fiable et ne prend pas en charge MSG_PARTIAL), les données excédentaires sont perdues et WSARecv génère l’erreur WSAEMSGSIZE.

Pour les sockets orientés connexion, WSARecv peut indiquer l’arrêt normal du circuit virtuel de l’une des deux manières qui dépendent du flux d’octets ou du message. Pour les flux d’octets, zéro octet ayant été lu (comme indiqué par une valeur de retour zéro pour indiquer la réussite et la valeur lpNumberOfBytesRecvd de zéro) indique une fermeture normale et qu’aucun autre octet ne sera jamais lu. Pour les sockets orientés message, où un message sans octet est souvent autorisé, un échec avec un code d’erreur WSAEDISCON est utilisé pour indiquer une fermeture normale. Dans tous les cas, un code d’erreur de retour de WSAECONNRESET indique qu’une fermeture avortée s’est produite.

Le paramètre lpFlags peut être utilisé pour influencer le comportement de l’appel de fonction au-delà des options spécifiées pour le socket associé. Autrement dit, la sémantique de cette fonction est déterminée par les options de socket et le paramètre lpFlags . Ce dernier est construit à l’aide de l’opérateur OR au niveau du bit avec l’une des valeurs répertoriées dans le tableau suivant.

Valeur Signification
MSG_PEEK Examine les données entrantes. Les données sont copiées dans la mémoire tampon, mais ne sont pas supprimées de la file d’attente d’entrée.

Cet indicateur est valide uniquement pour les sockets non survolés.

MSG_OOB Traite les données OOB.
MSG_PARTIAL Cet indicateur s’adresse uniquement aux sockets orientés message. Sur la sortie, cet indicateur indique que les données spécifiées sont une partie du message transmis par l’expéditeur. Les parties restantes du message seront spécifiées dans les opérations de réception suivantes. Une opération de réception ultérieure avec l’indicateur MSG_PARTIAL effacé indique la fin du message de l’expéditeur.

En tant que paramètre d’entrée, cet indicateur indique que l’opération de réception doit se terminer même si seule une partie d’un message a été reçue par le fournisseur de transport.

MSG_PUSH_IMMEDIATE Cet indicateur s’adresse uniquement aux sockets orientés flux. Cet indicateur permet à une application qui utilise des sockets de flux d’indiquer au fournisseur de transport de ne pas retarder l’achèvement des demandes de réception partiellement remplies en attente. Il s’agit d’un indicateur pour le fournisseur de transport que l’application est prête à recevoir toutes les données entrantes dès que possible sans nécessairement attendre le reste des données qui peuvent encore être en transit. Ce qui constitue une demande de réception en attente partiellement remplie est une question spécifique au transport.

Dans le cas de TCP, cela fait référence au cas où des segments TCP entrants sont placés dans la mémoire tampon de données de demande de réception où aucun des segments TCP n’a indiqué une valeur de bit PUSH de 1. Dans ce cas, TCP peut contenir la demande de réception partiellement remplie un peu plus longtemps pour permettre au reste des données d’arriver avec un segment TCP dont le bit PUSH est défini sur 1. Cet indicateur indique à TCP de ne pas conserver la demande de réception, mais de la terminer immédiatement.

L’utilisation de cet indicateur pour les transferts de blocs volumineux n’est pas recommandée, car le traitement des blocs partiels n’est souvent pas optimal. Cet indicateur n’est utile que dans les cas où la réception et le traitement des données partielles contribuent immédiatement à réduire la latence de traitement.

Cet indicateur est un indicateur plutôt qu’une garantie réelle.

Cet indicateur est pris en charge sur Windows 8.1, Windows Server 2012 R2 et versions ultérieures.

MSG_WAITALL La demande de réception ne se termine que lorsque l’un des événements suivants se produit :
  • La mémoire tampon fournie par l’appelant est complètement pleine.
  • La connexion a été fermée.
  • La demande a été annulée ou une erreur s’est produite.

N’oubliez pas que si le fournisseur de transport sous-jacent ne prend pas en charge MSG_WAITALL ou si le socket est en mode non bloquant, cet appel échoue avec WSAEOPNOTSUPP. En outre, si MSG_WAITALL est spécifié avec MSG_OOB, MSG_PEEK ou MSG_PARTIAL, cet appel échoue avec WSAEOPNOTSUPP.

Cet indicateur n’est pas pris en charge sur les sockets de datagrammes ou les sockets orientés message.

 

Pour les sockets orientés message, le bit MSG_PARTIAL est défini dans le paramètre lpFlags si un message partiel est reçu. Si un message complet est reçu, MSG_PARTIAL est effacé dans lpFlags. En cas d’achèvement différé, la valeur pointée par lpFlags n’est pas mise à jour. Lorsque l’achèvement a été indiqué, l’application doit appeler WSAGetOverlappedResult et examiner les indicateurs indiqués par le paramètre lpdwFlags .

Note Lors de l’émission d’un appel Winsock bloquant tel que WSARecv avec le paramètre lpOverlapped défini sur NULL, Winsock peut avoir besoin d’attendre qu’un événement réseau puisse se terminer. Winsock effectue une attente alertable dans cette situation, qui peut être interrompue par un appel de procédure asynchrone (APC) planifié sur le même thread. L’émission d’un autre appel Winsock bloquant à l’intérieur d’un APC qui a interrompu un appel Winsock bloquant en cours sur le même thread entraîne un comportement non défini et ne doit jamais être tenté par les clients Winsock.
 

E/S de sockets qui se chevauchent

Si une opération qui se chevauche se termine immédiatement, WSARecv retourne la valeur zéro et le paramètre lpNumberOfBytesRecvd est mis à jour avec le nombre d’octets reçus et les bits d’indicateur indiqués par le paramètre lpFlags sont également mis à jour. Si l’opération qui se chevauche est correctement lancée et se terminera ultérieurement, WSARecv retourne SOCKET_ERROR et indique le code d’erreur WSA_IO_PENDING. Dans ce cas, lpNumberOfBytesRecvd et lpFlags ne sont pas mis à jour. Une fois l’opération chevauchée terminée, la quantité de données transférées est indiquée via le paramètre cbTransferred dans la routine d’achèvement (si spécifié), ou via le paramètre lpcbTransfer dans WSAGetOverlappedResult. Les valeurs d’indicateur sont obtenues en examinant le paramètre lpdwFlags de WSAGetOverlappedResult.

La fonction WSARecv utilisant des E/S qui se chevauchent peut être appelée à partir de la routine d’achèvement d’une fonction WSARecvFrom, WSASend ou WSASendTo précédente. Pour un socket donné, les routines d’achèvement d’E/S ne sont pas imbriquées. Cela permet aux transmissions de données sensibles au temps de se produire entièrement dans un contexte préemptif.

Le paramètre lpOverlapped doit être valide pendant la durée de l’opération qui se chevauche. Si plusieurs opérations d’E/S sont simultanément en attente, chacune doit référencer une structure WSAOVERLAPPED distincte.

Si le paramètre lpCompletionRoutine a la valeur NULL, le paramètre hEvent de lpOverlapped est signalé lorsque l’opération qui se chevauche se termine s’il contient un handle d’objet d’événement valide. Une application peut utiliser WSAWaitForMultipleEvents ou WSAGetOverlappedResult pour attendre ou interroger l’objet d’événement.

Si lpCompletionRoutine n’a pas la valeur NULL, le paramètre hEvent est ignoré et peut être utilisé par l’application pour transmettre des informations de contexte à la routine d’achèvement. Un appelant qui passe un lpCompletionRoutine non NULL et appelle ultérieurement WSAGetOverlappedResult pour la même demande d’E/S qui se chevauche peut ne pas définir le paramètre fWait pour cet appel de WSAGetOverlappedResult sur TRUE. Dans ce cas, l’utilisation du paramètre hEvent n’est pas définie et une tentative d’attente sur le paramètre hEvent produirait des résultats imprévisibles.

La routine d’achèvement suit les mêmes règles que celles spécifiées pour les routines d’achèvement d’E/S de fichiers Windows. La routine d’achèvement n’est pas appelée tant que le thread n’est pas dans un état d’attente pouvant être alerté, comme cela peut se produire lorsque la fonction WSAWaitForMultipleEvents avec le paramètre fAlertable défini sur TRUE est appelée.

Le prototype de la routine d’achèvement est le suivant :


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

CompletionRoutine est un espace réservé pour un nom de fonction défini par l’application ou défini par la bibliothèque. DwError spécifie la status d’achèvement pour l’opération qui se chevauche, comme indiqué par lpOverlapped. Le paramètre cbTransferred spécifie le nombre d’octets reçus. Le paramètre dwFlags contient des informations qui auraient été affichées dans lpFlags si l’opération de réception s’était terminée immédiatement. Cette fonction ne retourne pas de valeur.

Le retour à partir de cette fonction permet d’appeler une autre routine d’achèvement en attente pour ce socket. Lors de l’utilisation de WSAWaitForMultipleEvents, toutes les routines d’achèvement en attente sont appelées avant que l’attente du thread pouvant être alerté soit satisfaite avec un code de retour de WSA_IO_COMPLETION. Les routines d’achèvement peuvent être appelées dans n’importe quel ordre, pas nécessairement dans le même ordre que les opérations qui se chevauchent. Toutefois, il est garanti que les mémoires tampons publiées soient remplies dans l’ordre dans lequel elles sont spécifiées.

Si vous utilisez des ports d’achèvement d’E/S, n’oubliez pas que l’ordre des appels effectués à WSARecv est également l’ordre dans lequel les mémoires tampons sont remplies. WSARecv ne doit pas être appelé simultanément sur le même socket à partir de différents threads, car cela peut entraîner un ordre de mémoire tampon imprévisible.

Exemple de code

L’exemple suivant montre comment utiliser la fonction WSARecv en mode d’E/S qui se chevauche.
#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 : cette fonction est prise en charge pour les applications Windows Phone Store sur Windows Phone 8 et versions ultérieures.

Windows 8.1 et Windows Server 2012 R2 : cette fonction est prise en charge pour les applications du Windows Store sur Windows 8.1, Windows Server 2012 R2 et versions ultérieures.

Configuration requise

   
Client minimal pris en charge Windows 8.1, Windows Vista [applications de bureau | Applications UWP]
Serveur minimal pris en charge Windows Server 2003 [applications de bureau | applications UWP]
Plateforme cible Windows
En-tête winsock2.h
Bibliothèque Ws2_32.lib
DLL Ws2_32.dll

Voir aussi

WSABUF

WSACloseEvent

WSACreateEvent

WSAGetOverlappedResult

WSAOVERLAPPED

WSASocket

WSAWaitForMultipleEvents

Winsock Functions

Référence Winsock

Recv