WSAWaitForMultipleEvents-Funktion (winsock2.h)

Die WSAWaitForMultipleEvents-Funktion gibt zurück, wenn sich eines oder alle der angegebenen Ereignisobjekte im signalierten Zustand befinden, das Timeoutintervall abläuft oder wenn eine E/A-Vervollständigungsroutine ausgeführt wurde.

Syntax

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

Parameter

[in] cEvents

Die Anzahl der Ereignisobjekthandles im Array, auf das von lphEvents verwiesen wird. Die maximale Anzahl von Ereignisobjekthandles ist WSA_MAXIMUM_WAIT_EVENTS. Mindestens ein Ereignis muss angegeben werden.

[in] lphEvents

Ein Zeiger auf ein Array von Ereignisobjekthandles. Das Array kann Handles von Objekten unterschiedlicher Typen enthalten. Es darf nicht mehrere Kopien desselben Handles enthalten, wenn der fWaitAll-Parameter auf TRUE festgelegt ist. Wenn eines dieser Handles geschlossen wird, während die Wartezeit noch aussteht, ist das Verhalten von WSAWaitForMultipleEvents nicht definiert.

Die Handles müssen über das Synchronize-Zugriffsrecht verfügen. Weitere Informationen finden Sie unter Standardzugriffsrechte.

[in] fWaitAll

Ein -Wert, der den Wartetyp angibt. True gibt die Funktion zurück, wenn der Zustand aller Objekte im lphEvents-Array signalisiert wird. Bei FALSE gibt die Funktion zurück, wenn eines der Ereignisobjekte signalisiert wird. Im letzteren Fall gibt der Rückgabewert minus WSA_WAIT_EVENT_0 den Index des Ereignisobjekts an, dessen Zustand dazu geführt hat, dass die Funktion zurückgegeben wurde. Wenn während des Aufrufs mehr als ein Ereignisobjekt signalisiert wurde, ist dies der Arrayindex für das signalierte Ereignisobjekt mit dem kleinsten Indexwert aller signalierten Ereignisobjekte.

[in] dwTimeout

Das Timeoutintervall in Millisekunden. WSAWaitForMultipleEvents gibt zurück, wenn das Timeoutintervall abläuft, auch wenn die vom fWaitAll-Parameter angegebenen Bedingungen nicht erfüllt sind. Wenn der dwTimeout-Parameter null ist, testet WSAWaitForMultipleEvents den Zustand der angegebenen Ereignisobjekte und gibt sofort zurück. Wenn dwTimeoutWSA_INFINITE ist, wartet WSAWaitForMultipleEvents ewig. Das heißt, das Timeoutintervall läuft nie ab.

[in] fAlertable

Ein -Wert, der angibt, ob der Thread in einen warnbaren Wartezustand versetzt wird, damit das System E/A-Vervollständigungsroutinen ausführen kann. Bei TRUE wird der Thread in einen warnbaren Wartezustand versetzt, und WSAWaitForMultipleEvents kann zurückgegeben werden, wenn das System eine E/A-Abschlussroutine ausführt. In diesem Fall wird WSA_WAIT_IO_COMPLETION zurückgegeben, und das Ereignis, auf das gewartet wurde, wird noch nicht signalisiert. Die Anwendung muss die WSAWaitForMultipleEvents-Funktion erneut aufrufen. Bei FALSE wird der Thread nicht in einen warnbaren Wartezustand versetzt, und E/A-Vervollständigungsroutinen werden nicht ausgeführt.

Rückgabewert

Wenn die WSAWaitForMultipleEvents-Funktion erfolgreich ist, ist der Rückgabewert bei Erfolg einer der folgenden Werte.

Rückgabewert Bedeutung
WSA_WAIT_EVENT_0 zu (WSA_WAIT_EVENT_0 + cEvents - 1)
Wenn der fWaitAll-ParameterTRUE ist, gibt der Rückgabewert an, dass alle angegebenen Ereignisobjekte signalisiert werden.

Wenn der fWaitAll-ParameterFALSE ist, gibt der Rückgabewert minus WSA_WAIT_EVENT_0 den lphEvents-Arrayindex des signalierten Ereignisobjekts an, das die Wartezeit erfüllt hat. Wenn während des Aufrufs mehrere Ereignisobjekte signalisiert wurden, gibt der Rückgabewert den lphEvents-Arrayindex des signalierten Ereignisobjekts mit dem kleinsten Indexwert aller signalisierten Ereignisobjekte an.

WSA_WAIT_IO_COMPLETION
Die Wartezeit wurde durch eine oder mehrere E/A-Abschlussroutinen beendet, die ausgeführt wurden. Das Ereignis, auf das gewartet wurde, wird noch nicht signalisiert. Die Anwendung muss die WSAWaitForMultipleEvents-Funktion erneut aufrufen. Dieser Rückgabewert kann nur zurückgegeben werden, wenn der fAlertable-ParameterTRUE ist.
WSA_WAIT_TIMEOUT
Das Timeoutintervall ist abgelaufen, und die vom fWaitAll-Parameter angegebenen Bedingungen wurden nicht erfüllt. Es wurden keine E/A-Vervollständigungsroutinen ausgeführt.
 

Wenn die WSAWaitForMultipleEvents-Funktion fehlschlägt , wird der Rückgabewert WSA_WAIT_FAILED. In der folgenden Tabelle sind Werte aufgeführt, die mit WSAGetLastError verwendet werden können, um erweiterte Fehlerinformationen abzurufen.

Fehlercode Bedeutung
WSANOTINITIALISED Vor der Verwendung dieser Funktion muss ein erfolgreicher WSAStartup-Aufruf erfolgen.
WSAENETDOWN Fehler beim Netzwerksubsystem.
WSAEINPROGRESS Ein blockierter Windows Sockets 1.1-Aufruf wird ausgeführt, oder der Dienstanbieter verarbeitet noch eine Rückruffunktion.
WSA_NOT_ENOUGH_MEMORY Es war nicht genügend freier Arbeitsspeicher verfügbar, um den Vorgang abzuschließen.
WSA_INVALID_HANDLE Mindestens einer der Werte im lphEvents-Array ist kein gültiges Ereignisobjekthandle.
WSA_INVALID_PARAMETER Der cEvents-Parameter enthält keine gültige Handleanzahl.

Hinweise

Die WSAWaitForMultipleEvents-Funktion bestimmt, ob die Wartekriterien erfüllt wurden. Wenn die Kriterien nicht erfüllt wurden, wechselt der aufrufende Thread in den Wartezustand. Beim Warten auf die Erfüllung der Kriterien wird keine Prozessorzeit verwendet.

Die WSAWaitForMultipleEvents-Funktion gibt zurück, wenn sich eines oder alle der angegebenen Objekte im signalierten Zustand befinden oder wenn das Timeoutintervall verstrichen ist.

Wenn der bWaitAll-ParameterTRUE ist, wird der Wartevorgang nur abgeschlossen, wenn der Status aller Objekte auf signalisiert festgelegt wurde. Die Funktion ändert die Zustände der angegebenen Objekte erst, wenn der Status aller Objekte auf signalisiert festgelegt wurde.

Wenn der bWaitAll-ParameterFALSE ist, überprüft WSAWaitForMultipleEvents die Handles im lphEvents-Array , beginnend mit Index 0, bis eines der Objekte signalisiert wird. Wenn mehrere Objekte signalisiert werden, gibt die Funktion den Index des ersten Handles im lphEvents-Array zurück, dessen Objekt signalisiert wurde.

Diese Funktion wird auch verwendet, um einen warnbaren Wartevorgang auszuführen, indem der fAlertable-Parameter auf TRUE festgelegt wird. Dadurch kann die Funktion zurückgeben, wenn das System eine E/A-Vervollständigungsroutine durch den aufrufenden Thread ausführt.

Ein Thread muss sich in einem warnbaren Wartezustand befinden, damit das System E/A-Vervollständigungsroutinen (asynchrone Prozeduraufrufe oder APCs) ausführen kann. Wenn also eine Anwendung WSAWaitForMultipleEvents aufruft , wenn asynchrone Vorgänge mit E/A-Vervollständigungsroutinen ausstehen und der fAlertable-ParameterFALSE ist, werden diese E/A-Vervollständigungsroutinen auch dann nicht ausgeführt, wenn diese E/A-Vorgänge abgeschlossen sind.

Wenn der fAlertable-ParameterTRUE ist und einer der ausstehenden Vorgänge abgeschlossen wird, wird der APC ausgeführt, und WSAWaitForMultipleEvents gibt WSA_IO_COMPLETION zurück. Das ausstehende Ereignis wird noch nicht signalisiert. Die Anwendung muss die WSAWaitForMultipleEvents-Funktion erneut aufrufen.

Anwendungen, die einen warnbaren Wartezustand erfordern, ohne darauf zu warten, dass Ereignisobjekte signalisiert werden, sollten die Windows SleepEx-Funktion verwenden.

Die aktuelle Implementierung von WSAWaitForMultipleEvents ruft die WaitForMultipleObjectsEx-Funktion auf.

Hinweis Gehen Sie vorsichtig vor, wenn Sie WSAWaitForMultipleEvents mit Code aufrufen, der direkt oder indirekt Fenster erstellt. Wenn ein Thread Fenster erstellt, muss er Meldungen verarbeiten. Nachrichtenübertragungen werden an alle Fenster im System gesendet. Ein Thread, der WSAWaitForMultipleEvents ohne Timeoutlimit verwendet (der dwTimeout-Parameter ist auf WSA_INFINITE festgelegt) kann dazu führen, dass das System deadlockt wird.
 

Beispielcode

Im folgenden Codebeispiel wird die Verwendung der WSAWaitForMultipleEvents-Funktion veranschaulicht.
#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: 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 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

Standardzugriffsrechte

WSACloseEvent

WSACreateEvent

WaitForMultipleObjectsEx

Winsock-Funktionen

Winsock-Referenz