Fonction WSARecvFrom (winsock2.h)

La fonction WSARecvFrom reçoit un datagramme et stocke l’adresse source.

Syntaxe

int WSAAPI WSARecvFrom(
  [in]      SOCKET                             s,
  [in, out] LPWSABUF                           lpBuffers,
  [in]      DWORD                              dwBufferCount,
  [out]     LPDWORD                            lpNumberOfBytesRecvd,
  [in, out] LPDWORD                            lpFlags,
  [out]     sockaddr                           *lpFrom,
  [in, out] LPINT                              lpFromlen,
  [in]      LPWSAOVERLAPPED                    lpOverlapped,
  [in]      LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

Paramètres

[in] s

Descripteur identifiant un socket.

[in, out] lpBuffers

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

[in] dwBufferCount

Nombre de structures WSABUF dans le tableau lpBuffers .

[out] lpNumberOfBytesRecvd

Pointeur vers le nombre d’octets reçus par cet appel si l’opération WSARecvFrom 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 WSARecvFrom . Consultez la section Notes ci-dessous.

[out] lpFrom

Pointeur facultatif vers une mémoire tampon qui contiendra l’adresse source à la fin de l’opération qui se chevauche.

[in, out] lpFromlen

Pointeur vers la taille, en octets, de la mémoire tampon « de » requise uniquement si lpFrom est spécifié.

[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 WSARecvFrom 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 s’est terminée immédiatement, WSARecvFrom 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
WSAECONNRESET
Le circuit virtuel a été rétabli par la partie distante exécutant une fermeture brutale ou infructueuse. L’application doit fermer le socket, car il n’est plus utilisable. Pour un socket de datagramme UPD, cette erreur indique qu’une opération d’envoi précédente a donné lieu à un message ICMP « Port inaccessible ».
WSAEFAULT
Le paramètre lpBuffers, lpFlags, lpFrom, lpNumberOfBytesRecvd, lpFromlen, lpOverlapped ou lpCompletionRoutine n’est pas entièrement contenu dans une partie valide de l’espace d’adressage utilisateur : la mémoire tampon lpFrom était trop petite pour prendre en charge l’adresse homologue.
WSAEINPROGRESS
Un appel bloquant Windows Sockets 1.1 est en cours ou le fournisseur de services traite toujours une fonction de rappel.
WSAEINTR
Un appel bloquant Windows Socket 1.1 a été annulé via WSACancelBlockingCall.
WSAEINVAL
Le socket n’a pas été lié (avec liaison, par exemple).
WSAEMSGSIZE
Le message était trop volumineux pour 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 datagramme, cette erreur indique que la durée de vie (TTL, Time to Live) a expiré.
WSAENOTCONN
Le socket n’est pas connecté (sockets orientés connexion uniquement).
WSAEWOULDBLOCK
Windows NT :

Sockets qui se chevauchent : 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 WSARecvFrom fournit des fonctionnalités au-delà de la fonction recvfrom standard dans trois domaines importants :

  • Il peut être utilisé conjointement avec des sockets qui se chevauchent pour effectuer des opérations de réception 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 à la fois un paramètre d’entrée et un paramètre de sortie, ce qui permet aux applications de détecter l’état de sortie du bit d’indicateur MSG_PARTIAL . N’oubliez pas que le bit d’indicateur MSG_PARTIAL n’est pas pris en charge par tous les protocoles.
La fonction WSARecvFrom est principalement utilisée sur un socket sans connexion spécifié par s. L’adresse locale du socket doit être connue. Pour les applications serveur, cela se fait généralement explicitement par le biais de la liaison. La liaison explicite est déconseillée pour les applications clientes. Pour les applications clientes utilisant cette fonction, le socket peut devenir implicitement lié à une adresse locale via sendto, WSASendTo ou WSAJoinLeaf.

Pour les sockets qui se chevauchent, cette fonction est utilisée pour publier une ou plusieurs mémoires tampons dans lesquelles les données entrantes seront placées à mesure qu’elles seront disponibles sur un socket (éventuellement connecté), 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. En outre, les valeurs indiquées par lpFrom et lpFromlen ne sont pas mises à jour tant que l’achèvement n’est pas lui-même indiqué. Les applications ne doivent pas utiliser ou perturber ces valeurs tant qu’elles n’ont pas été mises à jour ; Par conséquent, l’application ne doit pas utiliser de variables automatiques (c’est-à-dire basées sur la pile) pour ces paramètres.

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 WSARecv 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. 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 sera bloqué jusqu’à ce que les données soient reçues.

Les mémoires tampons sont remplies dans l’ordre dans lequel elles apparaissent dans le tableau indiqué 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 types de sockets sans connexion, l’adresse à partir de laquelle les données proviennent est copiée dans la mémoire tampon indiquée par lpFrom. La valeur pointée par lpFromlen est initialisée à la taille de cette mémoire tampon et est modifiée à l’achèvement pour indiquer la taille réelle de l’adresse qui y est stockée. Comme indiqué précédemment pour les sockets qui se chevauchent, les paramètres lpFrom et lpFromlen ne sont mis à jour qu’une fois les E/S superposées terminées. La mémoire indiquée par ces paramètres doit donc rester disponible pour le fournisseur de services et ne peut pas être allouée sur le cadre de pile de l’application. Les paramètres lpFrom et lpFromlen sont ignorés pour les sockets orientés connexion.

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 sont remplies.
  • La connexion est fermée.
  • Les données mises en mémoire tampon en interne sont é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, 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, WSARecvFrom 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 WSARecvFrom génère l’erreur WSAEMSGSIZE.

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 . Cette dernière est construite à 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 Affiche un aperçu des 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. En sortie, cet indicateur indique que les données sont une partie du message transmis par l’expéditeur. Les parties restantes du message seront transmises lors des opérations de réception suivantes. Une opération de réception ultérieure avec MSG_PARTIAL indicateur 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 services.

 

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 pointés par le paramètre lpdwFlags .

Note Lors de l’émission d’un appel Winsock bloquant tel que WSARecvFrom avec le paramètre lpOverlapped défini sur NULL, Winsock peut avoir besoin d’attendre qu’un événement réseau se termine. 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, WSARecvFrom retourne une valeur de zéro et le paramètre lpNumberOfBytesRecvd est mis à jour avec le nombre d’octets reçus et les bits d’indicateur pointé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, WSARecvFrom retourne SOCKET_ERROR et indique le code d’erreur WSA_IO_PENDING. Dans ce cas, lpNumberOfBytesRecvd et lpFlags ne sont pas mis à jour. Lorsque l’opération qui se chevauche se termine, la quantité de données transférées est indiquée par le biais du paramètre cbTransferred dans la routine d’achèvement (si spécifié), ou par le biais du paramètre lpcbTransfer dans WSAGetOverlappedResult. Les valeurs d’indicateur sont obtenues par le biais du paramètre dwFlags de la routine d’achèvement, ou en examinant le paramètre lpdwFlags de WSAGetOverlappedResult.

La fonction WSARecvFrom peut être appelée à partir de la routine d’achèvement d’une fonction WSARecvFrom, 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.

Si un port d’achèvement d’E/S est utilisé et que le paramètre lpCompletionRoutine et le paramètre hEvent sont NULL, le résultat de l’opération est planifié sur le port d’achèvement des E/S. Cela se produit pour toutes les opérations réussies, que les opérations se terminent immédiatement ou non.

Les fournisseurs de transport permettent à une application d’appeler des opérations d’envoi et de réception à partir du contexte de la routine d’achèvement des E/S du socket et garantissent que, pour un socket donné, les routines d’achèvement des E/S ne seront pas imbriquées. Cela permet aux transmissions de données sensibles au temps de se produire entièrement dans un contexte préemptif.

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 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 alertable 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 spécifié.

Exemple de code

L’exemple suivant illustre l’utilisation de la fonction WSARecvFrom .
#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

int __cdecl main()
{

    WSADATA wsaData;
    WSABUF DataBuf;
    WSAOVERLAPPED Overlapped;

    SOCKET RecvSocket = INVALID_SOCKET;
    struct sockaddr_in RecvAddr;
    struct sockaddr_in SenderAddr;

    int SenderAddrSize = sizeof (SenderAddr);
    u_short Port = 27015;

    char RecvBuf[1024];
    int BufLen = 1024;
    DWORD BytesRecv = 0;
    DWORD Flags = 0;

    int err = 0;
    int rc;
    int retval = 0;
    
    //-----------------------------------------------
    // Initialize Winsock
    rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (rc != 0) {
        /* Could not find a usable Winsock DLL */
        wprintf(L"WSAStartup failed with error: %ld\n", rc);
        return 1;
    }

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

    // Create an event handle and setup the overlapped structure.
    Overlapped.hEvent = WSACreateEvent();
    if (Overlapped.hEvent == NULL) {
        wprintf(L"WSACreateEvent failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    //-----------------------------------------------
    // Create a receiver socket to receive datagrams
    RecvSocket = WSASocket(AF_INET,
                           SOCK_DGRAM,
                           IPPROTO_UDP, NULL, 0, WSA_FLAG_OVERLAPPED);

    if (RecvSocket == INVALID_SOCKET) {
        /* Could not open a socket */
        wprintf(L"WSASocket failed with error: %ld\n", WSAGetLastError());
        WSACloseEvent(Overlapped.hEvent);
        WSACleanup();
        return 1;
    }
    //-----------------------------------------------
    // Bind the socket to any address and the specified port.
    RecvAddr.sin_family = AF_INET;
    RecvAddr.sin_port = htons(Port);
    RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    rc = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
    if (rc != 0) {
        /* Bind to the socket failed */
        wprintf(L"bind failed with error: %ld\n", WSAGetLastError());
        WSACloseEvent(Overlapped.hEvent);
        closesocket(RecvSocket);
        WSACleanup();
        return 1;
    }

    //-----------------------------------------------
    // Call the recvfrom function to receive datagrams
    // on the bound socket.
    DataBuf.len = BufLen;
    DataBuf.buf = RecvBuf;
    wprintf(L"Listening for incoming datagrams on port=%d\n", Port);
    rc = WSARecvFrom(RecvSocket,
                      &DataBuf,
                      1,
                      &BytesRecv,
                      &Flags,
                      (SOCKADDR *) & SenderAddr,
                      &SenderAddrSize, &Overlapped, NULL);

    if (rc != 0) {
        err = WSAGetLastError();
        if (err != WSA_IO_PENDING) {
            wprintf(L"WSARecvFrom failed with error: %ld\n", err);
            WSACloseEvent(Overlapped.hEvent);
            closesocket(RecvSocket);
            WSACleanup();
            return 1;
        }
        else {
            rc = WSAWaitForMultipleEvents(1, &Overlapped.hEvent, TRUE, INFINITE, TRUE);
            if (rc == WSA_WAIT_FAILED) {
                wprintf(L"WSAWaitForMultipleEvents failed with error: %d\n", WSAGetLastError());
                retval = 1;
            }

            rc = WSAGetOverlappedResult(RecvSocket, &Overlapped, &BytesRecv,
                                FALSE, &Flags);
            if (rc == FALSE) {
                wprintf(L"WSArecvFrom failed with error: %d\n", WSAGetLastError());
                retval = 1;
            }
            else
                wprintf(L"Number of received bytes = %d\n", BytesRecv);
                
            wprintf(L"Finished receiving. Closing socket.\n");
        }
        
    }
    //---------------------------------------------
    // When the application is finished receiving, close the socket.

    WSACloseEvent(Overlapped.hEvent);
    closesocket(RecvSocket);
    wprintf(L"Exiting.\n");

    //---------------------------------------------
    // Clean up and quit.
    WSACleanup();
    return (retval);
}

Windows Phone 8 : cette fonction est prise en charge pour les applications du Store Windows Phone 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

WSASend

WSASendTo

WSASocket

WSAWaitForMultipleEvents

Fonctions Winsock

Informations de référence sur Winsock

Sendto