WSAWaitForMultipleEvents
A version of this page is also available for
4/8/2010
This function waits for multiple events and returns either when one or all of the specified event objects are in the signaled state, or when the timeout interval expires.
Syntax
DWORD WSAAPI WSAWaitForMultipleEvents(
DWORD cEvents,
const WSAEVENT FAR* lphEvents,
BOOL fWaitAll,
DWORD dwTimeout,
BOOL fAlertable
);
Parameters
- cEvents
[in] The number of event object handles in the array indicated by lphEvents. The maximum number of event object handles is WSA_MAXIMUM_WAIT_EVENTS. One or more events must be specified.
- lphEvents
[in] Pointer to an array of event object handles.
- fWaitAll
[in] Indication of the wait type. This parameter must be set to FALSE. This causes the function to return when any of the event objects is signaled. When set to FALSE, the return value indicates the event object having the state that caused the function to return.
- dwTimeout
[in] The timeout interval, in milliseconds. The function returns if the interval expires, even if conditions specified by the fWaitAll parameter are not satisfied. If dwTimeout is set to zero, the function tests the state of the specified event objects and returns immediately. If dwTimeout is set to WSA_INFINITE, the timeout interval never expires.
- fAlertable
[in] Indicator specifying whether the function returns when the system queues an I/O completion routine for execution by the calling thread. If TRUE, the completion routine is executed and the function returns. If FALSE, the completion routine is not executed when the function returns.
Return Values
If the WSAWaitForMultipleEvents function succeeds, the return value indicates the event object that caused the function to return. The following table shows the return values upon success.
Value | Description |
---|---|
WSA_WAIT_EVENT_0 to (WSA_WAIT_EVENT_0 + cEvents - 1) |
If fWaitAll is TRUE, the return value indicates that the state of all specified event objects is signaled. If fWaitAll is FALSE, the return value minus WSA_WAIT_EVENT_0 indicates the lphEvents array index of the object that satisfied the wait. |
WAIT_IO_COMPLETION |
One or more I/O completion routines are queued for execution. |
WSA_WAIT_TIMEOUT |
The timeout interval elapsed and the conditions specified by the fWaitAll parameter were not satisfied. |
If the function fails, the return value is WSA_WAIT_FAILED. To get extended error information, call WSAGetLastError. The following table shows the possible extended error codes.
Error code | Description |
---|---|
WSANOTINITIALISED |
A successful WSAStartup call must occur before using this function. |
WSAENETDOWN |
The network subsystem has failed. |
WSAEINPROGRESS |
A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. |
WSA_NOT_ENOUGH_MEMORY |
Not enough free memory available to complete the operation. |
WSA_INVALID_HANDLE |
One or more of the values in the lphEvents array is not a valid event object handle. |
WSA_INVALID_PARAMETER |
The cEvents parameter does not contain a valid handle count. |
Remarks
In addition to waiting for multiple events, the WSAWaitForMultipleEvents function can also perform an alertable wait when the fAlertable parameter is set to TRUE. This setting enables the function to return when the system queues an I/O completion routine to be executed by the calling thread.
When fWaitAll is TRUE, the wait condition is satisfied only when the state of all objects is signaled at the same time. The function does not modify the state of the specified objects until all objects are simultaneously signaled.
Applications that simply need to enter an alertable wait state without waiting for any event objects to be signaled should use the Windows SleepEx function.
Example Code
The following example demonstrates the use of the WSAWaitForMultipleEvents function.
#include <stdio.h>
#include "winsock2.h"
#define DATA_BUFSIZE 4096
void main() {
//-----------------------------------------
// Declare and initialize variables
WSABUF DataBuf;
char buffer[DATA_BUFSIZE];
DWORD EventTotal = 0,
RecvBytes = 0,
Flags = 0,
BytesTransferred = 0,
CallBack = 0;
WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
WSAOVERLAPPED AcceptOverlapped;
SOCKET ListenSocket, AcceptSocket;
//-----------------------------------------
// Initialize Winsock
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
//-----------------------------------------
// Create a listening socket bound to a local
// IP address and the port specified
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
u_short port = 27015;
char* ip;
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_port = htons(port);
hostent* thisHost;
thisHost = gethostbyname("");
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
bind(ListenSocket, (SOCKADDR *) &service, sizeof(SOCKADDR));
//-----------------------------------------
// Set the socket to listen for incoming
// connection requests
listen(ListenSocket, 1);
printf("Listening...\n");
//-----------------------------------------
// Accept and incoming connection request
AcceptSocket = accept(ListenSocket, NULL, NULL);
printf("Client Accepted...\n");
//-----------------------------------------
// Create an event handle and setup an overlapped structure.
EventArray[EventTotal] = WSACreateEvent();
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) {
if (WSAGetLastError() != WSA_IO_PENDING)
printf("Error occurred at WSARecv()\n");
}
//-----------------------------------------
// Process overlapped receives on the socket
while (1) {
DWORD Index;
//-----------------------------------------
// Wait for the overlapped I/O call to complete
Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE);
//-----------------------------------------
// Reset the signaled event
WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
//-----------------------------------------
// Determine the status of the overlapped event
WSAGetOverlappedResult(AcceptSocket, &AcceptOverlapped, &BytesTransferred, FALSE, &Flags);
//-----------------------------------------
// If the connection has been closed, close the accepted socket
if (BytesTransferred == 0) {
printf("Closing Socket %d\n", AcceptSocket);
closesocket(AcceptSocket);
WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]);
return;
}
//-----------------------------------------
// If data has been received, echo the received data
// from DataBuf back to the client
if (WSASend(AcceptSocket, &DataBuf, 1, &RecvBytes, Flags, &AcceptOverlapped, NULL) == SOCKET_ERROR)
printf("WSASend() is busted\n");
//-----------------------------------------
// 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;
}
}
Requirements
Header | winsock2.h |
Library | Ws2.lib |
Windows Embedded CE | Windows CE .NET 4.0 and later |
Windows Mobile | Windows Mobile Version 5.0 and later |
See Also
Reference
Winsock API Reference
Winsock Functions
WSACloseEvent
WSACreateEvent