WSAWaitForMultipleEvents

A version of this page is also available for

Windows Embedded CE 6.0 R3

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