Partager via


Fonction WSAWaitForMultipleEvents (winsock2.h)

La fonction WSAWaitForMultipleEvents retourne quand un ou tous les objets d’événement spécifiés sont à l’état signalé, lorsque l’intervalle de délai d’expiration expire ou lorsqu’une routine d’achèvement d’E/S a été exécutée.

Syntaxe

DWORD WSAAPI WSAWaitForMultipleEvents(
  [in] DWORD          cEvents,
  [in] const WSAEVENT *lphEvents,
  [in] BOOL           fWaitAll,
  [in] DWORD          dwTimeout,
  [in] BOOL           fAlertable
);

Paramètres

[in] cEvents

Nombre de handles d’objet d’événement dans le tableau pointé vers lphEvents. Le nombre maximal de handles d’objet d’événement est WSA_MAXIMUM_WAIT_EVENTS. Un ou plusieurs événements doivent être spécifiés.

[in] lphEvents

Pointeur vers un tableau de handles d’objet d’événement. Le tableau peut contenir des handles d’objets de différents types. Il peut ne pas contenir plusieurs copies du même handle si le paramètre fWaitAll a la valeur TRUE. Si l’un de ces handles est fermé alors que l’attente est toujours en attente, le comportement de WSAWaitForMultipleEvents n’est pas défini.

Les handles doivent avoir le droit d’accès SYNCHRONIZE . Pour plus d’informations, consultez Droits d’accès standard.

[in] fWaitAll

Valeur qui spécifie le type d’attente. Si la valeur est TRUE, la fonction retourne quand l’état de tous les objets du tableau lphEvents est signalé. Si la valeur est FALSE, la fonction retourne quand l’un des objets d’événement est signalé. Dans ce dernier cas, la valeur de retour moins WSA_WAIT_EVENT_0 indique l’index de l’objet d’événement dont l’état a provoqué le retour de la fonction. Si plusieurs objets d’événement ont été signalés pendant l’appel, il s’agit de l’index de tableau de l’objet événement signalé avec la plus petite valeur d’index de tous les objets d’événements signalés.

[in] dwTimeout

Intervalle de délai d’attente, en millisecondes. WSAWaitForMultipleEvents retourne si l’intervalle de délai d’expiration expire, même si les conditions spécifiées par le paramètre fWaitAll ne sont pas satisfaites. Si le paramètre dwTimeout est égal à zéro, WSAWaitForMultipleEvents teste l’état des objets d’événement spécifiés et retourne immédiatement. Si dwTimeout est WSA_INFINITE, WSAWaitForMultipleEvents attend toujours ; autrement dit, l’intervalle de délai d’expiration n’expire jamais.

[in] fAlertable

Valeur qui spécifie si le thread est placé dans un état d’attente pouvant être alerté afin que le système puisse exécuter des routines d’achèvement d’E/S. Si la valeur est TRUE, le thread est placé dans un état d’attente pouvant être alerté et WSAWaitForMultipleEvents peut retourner lorsque le système exécute une routine d’achèvement d’E/S. Dans ce cas, WSA_WAIT_IO_COMPLETION est retourné et l’événement attendu n’est pas encore signalé. L’application doit appeler à nouveau la fonction WSAWaitForMultipleEvents . Si la valeur est FALSE, le thread n’est pas placé dans un état d’attente pouvant être alerté et les routines d’achèvement des E/S ne sont pas exécutées.

Valeur retournée

Si la fonction WSAWaitForMultipleEvents réussit, la valeur de retour en cas de réussite est l’une des valeurs suivantes.

Valeur renvoyée Signification
WSA_WAIT_EVENT_0 à (WSA_WAIT_EVENT_0 + cEvents - 1)
Si le paramètre fWaitAll a la valeur TRUE, la valeur de retour indique que tous les objets d’événement spécifiés sont signalés.

Si le paramètre fWaitAll a la valeur FALSE, la valeur de retour moins WSA_WAIT_EVENT_0 indique l’index du tableau lphEvents de l’objet événement signalé qui a satisfait l’attente. Si plusieurs objets d’événement ont été signalés pendant l’appel, la valeur de retour indique l’index du tableau lphEvents de l’objet événement signalé avec la plus petite valeur d’index de tous les objets d’événements signalés.

WSA_WAIT_IO_COMPLETION
L’attente a été terminée par une ou plusieurs routines d’achèvement d’E/S exécutées. L’événement attendu n’est pas encore signalé. L’application doit appeler à nouveau la fonction WSAWaitForMultipleEvents . Cette valeur de retour ne peut être retournée que si le paramètre fAlertable a la valeur TRUE.
WSA_WAIT_TIMEOUT
L’intervalle de délai d’attente s’est écoulé et les conditions spécifiées par le paramètre fWaitAll n’ont pas été remplies. Aucune routine de saisie semi-automatique n’a été exécutée.
 

Si la fonction WSAWaitForMultipleEvents échoue, la valeur de retour est WSA_WAIT_FAILED. Le tableau suivant répertorie les valeurs qui peuvent être utilisées avec WSAGetLastError pour obtenir des informations d’erreur étendues.

Code d'erreur Signification
WSANOTINITIALISED Un appel WSAStartup réussi doit se produire avant d’utiliser cette fonction.
WSAENETDOWN Le sous-système réseau a échoué.
WSAEINPROGRESS Un appel bloquant Windows Sockets 1.1 est en cours ou le fournisseur de services traite toujours une fonction de rappel.
WSA_NOT_ENOUGH_MEMORY La mémoire libre n’était pas suffisante pour terminer l’opération.
WSA_INVALID_HANDLE Une ou plusieurs des valeurs du tableau lphEvents n’est pas un handle d’objet d’événement valide.
WSA_INVALID_PARAMETER Le paramètre cEvents ne contient pas de handle count valide.

Remarques

La fonction WSAWaitForMultipleEvents détermine si les critères d’attente ont été remplis. Si les critères n’ont pas été remplis, le thread appelant entre dans l’état d’attente. Il n’utilise pas de temps processeur en attendant que les critères soient remplis.

La fonction WSAWaitForMultipleEvents retourne quand un ou tous les objets spécifiés sont à l’état signalé, ou lorsque l’intervalle de délai d’expiration s’écoule.

Lorsque le paramètre bWaitAll a la valeur TRUE, l’opération d’attente est terminée uniquement lorsque les états de tous les objets ont été définis sur signalés. La fonction ne modifie pas les états des objets spécifiés tant que les états de tous les objets n’ont pas été définis sur signal.

Lorsque le paramètre bWaitAll a la valeur FALSE, WSAWaitForMultipleEvents vérifie les handles dans le tableau lphEvents dans l’ordre commençant par l’index 0, jusqu’à ce qu’un des objets soit signalé. Si plusieurs objets sont signalés, la fonction retourne l’index du premier handle du tableau lphEvents dont l’objet a été signalé.

Cette fonction est également utilisée pour effectuer une attente pouvant être alertée en définissant le paramètre fAlertable sur TRUE. Cela permet à la fonction de retourner lorsque le système exécute une routine d’achèvement d’E/S par le thread appelant.

Un thread doit être dans un état d’attente pouvant être alerté pour que le système puisse exécuter des routines d’achèvement d’E/S (appels de procédure asynchrone ou API). Par conséquent, si une application appelle WSAWaitForMultipleEvents quand des opérations asynchrones en attente ont des routines d’achèvement d’E/S et que le paramètre fAlertable a la valeur FALSE, ces routines d’achèvement d’E/S ne seront pas exécutées même si ces opérations d’E/S sont terminées.

Si le paramètre fAlertable a la valeur TRUE et si l’une des opérations en attente se termine, l’APC est exécuté et WSAWaitForMultipleEvents retourne WSA_IO_COMPLETION. L’événement en attente n’est pas encore signalé. L’application doit appeler à nouveau la fonction WSAWaitForMultipleEvents .

Les applications qui nécessitent un état d’attente pouvant être alerté sans attendre que des objets d’événement soient signalés doivent utiliser la fonction Windows SleepEx .

L’implémentation actuelle de WSAWaitForMultipleEvents appelle la fonction WaitForMultipleObjectsEx .

Note Soyez prudent lorsque vous appelez WSAWaitForMultipleEvents avec du code qui crée directement ou indirectement des fenêtres. Si un thread crée des fenêtres, il doit traiter les messages. Les diffusions de messages sont envoyées à toutes les fenêtres du système. Un thread qui utilise WSAWaitForMultipleEvents sans limite de délai d’attente (le paramètre dwTimeout défini sur WSA_INFINITE) peut entraîner l’interblocage du système.
 

Exemple de code

L’exemple de code suivant montre comment utiliser la fonction WSAWaitForMultipleEvents .
#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

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

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

#define DATA_BUFSIZE 4096

int main()
{
    //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData = { 0 };
    int iResult = 0;
    BOOL bResult = TRUE;

    WSABUF DataBuf;
    char buffer[DATA_BUFSIZE];

    DWORD EventTotal = 0;
    DWORD RecvBytes = 0;
    DWORD Flags = 0;
    DWORD BytesTransferred = 0;

    WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
    WSAOVERLAPPED AcceptOverlapped;
    SOCKET ListenSocket = INVALID_SOCKET;
    SOCKET AcceptSocket = INVALID_SOCKET;

    DWORD Index;

    //-----------------------------------------
    // Initialize Winsock
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        wprintf(L"WSAStartup failed: %d\n", iResult);
        return 1;
    }
    //-----------------------------------------
    // Create a listening socket bound to a local
    // IP address and the port specified
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {
        wprintf(L"socket failed with error = %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    u_short port = 27015;
    char *ip;
    sockaddr_in service;
    service.sin_family = AF_INET;
    service.sin_port = htons(port);
    hostent *thisHost;

    thisHost = gethostbyname("");
    if (thisHost == NULL) {
        wprintf(L"gethostbyname failed with error = %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    ip = inet_ntoa(*(struct in_addr *) *thisHost->h_addr_list);

    service.sin_addr.s_addr = inet_addr(ip);

    //-----------------------------------------
    // Bind the listening socket to the local IP address
    // and port number
    iResult = bind(ListenSocket, (SOCKADDR *) & service, sizeof (SOCKADDR));
    if (iResult != 0) {
        wprintf(L"bind failed with error = %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    //-----------------------------------------
    // Set the socket to listen for incoming
    // connection requests
    iResult = listen(ListenSocket, 1);
    if (iResult != 0) {
        wprintf(L"listen failed with error = %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    wprintf(L"Listening...\n");

    //-----------------------------------------
    // Accept and incoming connection request
    AcceptSocket = accept(ListenSocket, NULL, NULL);
    if (AcceptSocket == INVALID_SOCKET) {
        wprintf(L"accept failed with error = %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    wprintf(L"Client Accepted...\n");

    //-----------------------------------------
    // Create an event handle and setup an overlapped structure.
    EventArray[EventTotal] = WSACreateEvent();
    if (EventArray[EventTotal] == WSA_INVALID_EVENT) {
        wprintf(L"WSACreateEvent failed with error = %d\n", WSAGetLastError());
        closesocket(AcceptSocket);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    ZeroMemory(&AcceptOverlapped, sizeof (WSAOVERLAPPED));
    AcceptOverlapped.hEvent = EventArray[EventTotal];

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

    EventTotal++;

    //-----------------------------------------
    // Call WSARecv to receive data into DataBuf on 
    // the accepted socket in overlapped I/O mode
    if (WSARecv(AcceptSocket, &DataBuf, 1, &RecvBytes, &Flags, &AcceptOverlapped, NULL) ==
        SOCKET_ERROR) {
        iResult = WSAGetLastError();
        if (iResult != WSA_IO_PENDING)
            wprintf(L"WSARecv failed with error = %d\n", iResult);
    }
    //-----------------------------------------
    // Process overlapped receives on the socket
    while (1) {

        //-----------------------------------------
        // Wait for the overlapped I/O call to complete
        Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE);

        //-----------------------------------------
        // Reset the signaled event
        bResult = WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
        if (bResult == FALSE) {
            wprintf(L"WSAResetEvent failed with error = %d\n", WSAGetLastError());
        }
        //-----------------------------------------
        // Determine the status of the overlapped event
        bResult =
            WSAGetOverlappedResult(AcceptSocket, &AcceptOverlapped, &BytesTransferred, FALSE,
                                   &Flags);
        if (bResult == FALSE) {
            wprintf(L"WSAGetOverlappedResult failed with error = %d\n", WSAGetLastError());
        }
        //-----------------------------------------
        // If the connection has been closed, close the accepted socket
        if (BytesTransferred == 0) {
            wprintf(L"Closing accept Socket %d\n", AcceptSocket);
            closesocket(ListenSocket);
            closesocket(AcceptSocket);
            WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
            WSACleanup();
            return 1;
        }
        //-----------------------------------------
        // If data has been received, echo the received data
        // from DataBuf back to the client
        iResult =
            WSASend(AcceptSocket, &DataBuf, 1, &RecvBytes, Flags, &AcceptOverlapped, NULL);
        if (iResult != 0) {
            wprintf(L"WSASend failed with error = %d\n", WSAGetLastError());
        }
        //-----------------------------------------         
        // Reset the changed flags and overlapped structure
        Flags = 0;
        ZeroMemory(&AcceptOverlapped, sizeof (WSAOVERLAPPED));

        AcceptOverlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];

        //-----------------------------------------
        // Reset the data buffer
        DataBuf.len = DATA_BUFSIZE;
        DataBuf.buf = buffer;
    }

    closesocket(ListenSocket);
    closesocket(AcceptSocket);
    WSACleanup();

    return 0;
}


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

Droits d’accès standard

WSACloseEvent

WSACreateEvent

WaitForMultipleObjectsEx

Winsock Functions

Référence Winsock