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 |
---|---|
|
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. |
|
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. |
|
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.
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 |