Función WSAWaitForMultipleEvents (winsock2.h)
La función WSAWaitForMultipleEvents devuelve cuando uno o todos los objetos de evento especificados están en estado señalado, cuando expira el intervalo de tiempo de espera o cuando se ha ejecutado una rutina de finalización de E/S.
Sintaxis
DWORD WSAAPI WSAWaitForMultipleEvents(
[in] DWORD cEvents,
[in] const WSAEVENT *lphEvents,
[in] BOOL fWaitAll,
[in] DWORD dwTimeout,
[in] BOOL fAlertable
);
Parámetros
[in] cEvents
Número de identificadores de objeto de evento en la matriz a la que apunta lphEvents. El número máximo de identificadores de objeto de evento es WSA_MAXIMUM_WAIT_EVENTS. Se deben especificar uno o varios eventos.
[in] lphEvents
Puntero a una matriz de identificadores de objeto de evento. La matriz puede contener identificadores de objetos de diferentes tipos. Puede que no contenga varias copias del mismo identificador si el parámetro fWaitAll está establecido en TRUE. Si se cierra uno de estos identificadores mientras la espera sigue pendiente, el comportamiento de WSAWaitForMultipleEvents no está definido.
Los identificadores deben tener el derecho de acceso SYNCHRONIZE . Para obtener más información, consulte Derechos de acceso estándar.
[in] fWaitAll
Valor que especifica el tipo de espera. Si es TRUE, la función devuelve cuando se señala el estado de todos los objetos de la matriz lphEvents . Si es FALSE, la función devuelve cuando se señala cualquiera de los objetos de evento. En este último caso, el valor devuelto menos WSA_WAIT_EVENT_0 indica el índice del objeto de evento cuyo estado hizo que la función devolva. Si se señalizó más de un objeto de evento durante la llamada, este es el índice de matriz para el objeto de evento señalado con el valor de índice más pequeño de todos los objetos de evento señalados.
[in] dwTimeout
El intervalo de tiempo de espera en milisegundos. WSAWaitForMultipleEvents devuelve si expira el intervalo de tiempo de espera, incluso si no se cumplen las condiciones especificadas por el parámetro fWaitAll . Si el parámetro dwTimeout es cero, WSAWaitForMultipleEvents comprueba el estado de los objetos de evento especificados y devuelve inmediatamente. Si dwTimeout es WSA_INFINITE, WSAWaitForMultipleEvents espera para siempre; es decir, el intervalo de tiempo de espera nunca expira.
[in] fAlertable
Valor que especifica si el subproceso se coloca en un estado de espera alertable para que el sistema pueda ejecutar rutinas de finalización de E/S. Si es TRUE, el subproceso se coloca en un estado de espera alertable y WSAWaitForMultipleEvents puede devolver cuando el sistema ejecuta una rutina de finalización de E/S. En este caso, se devuelve WSA_WAIT_IO_COMPLETION y aún no se señala el evento en el que se estaba esperando. La aplicación debe llamar de nuevo a la función WSAWaitForMultipleEvents . Si es FALSE, el subproceso no se coloca en un estado de espera alertable y no se ejecutan las rutinas de finalización de E/S.
Valor devuelto
Si la función WSAWaitForMultipleEvents se realiza correctamente, el valor devuelto tras el éxito es uno de los siguientes valores.
Valor devuelto | Significado |
---|---|
|
Si el parámetro fWaitAll es TRUE, el valor devuelto indica que se señalizan todos los objetos de evento especificados.
Si el parámetro fWaitAll es FALSE, el valor devuelto menos WSA_WAIT_EVENT_0 indica el índice de matriz lphEvents del objeto de evento señalado que cumplió la espera. Si se señala más de un objeto de evento durante la llamada, el valor devuelto indica el índice de matriz lphEvents del objeto de evento señalado con el valor de índice más pequeño de todos los objetos de evento señalados. |
|
La espera finalizó con una o varias rutinas de finalización de E/S que se ejecutaron. Todavía no se señala el evento en el que se estaba esperando. La aplicación debe llamar de nuevo a la función WSAWaitForMultipleEvents . Este valor devuelto solo se puede devolver si el parámetro fAlertable es TRUE. |
|
No se cumplió el intervalo de tiempo de espera y las condiciones especificadas por el parámetro fWaitAll . No se ejecutaron rutinas de finalización de E/S. |
Si se produce un error en la función WSAWaitForMultipleEvents , el valor devuelto es WSA_WAIT_FAILED. En la tabla siguiente se enumeran los valores que se pueden usar con WSAGetLastError para obtener información de error extendida.
Código de error | Significado |
---|---|
WSANOTINITIALISED | Debe producirse una llamada de WSAStartup correcta antes de usar esta función. |
WSAENETDOWN | Error en el subsistema de red. |
WSAEINPROGRESS | Una llamada de Bloqueo de Windows Sockets 1.1 está en curso o el proveedor de servicios sigue procesando una función de devolución de llamada. |
WSA_NOT_ENOUGH_MEMORY | No había suficiente memoria libre disponible para completar la operación. |
WSA_INVALID_HANDLE | Uno o varios de los valores de la matriz lphEvents no son un identificador de objeto de evento válido. |
WSA_INVALID_PARAMETER | El parámetro cEvents no contiene un recuento de identificadores válido. |
Comentarios
La función WSAWaitForMultipleEvents determina si se han cumplido los criterios de espera. Si no se han cumplido los criterios, el subproceso que realiza la llamada entra en el estado de espera. No usa tiempo de procesador mientras espera a que se cumplan los criterios.
La función WSAWaitForMultipleEvents devuelve cuando cualquiera o todos los objetos especificados están en estado señalado o cuando transcurre el intervalo de tiempo de espera.
Cuando el parámetro bWaitAll es TRUE, la operación de espera solo se completa cuando los estados de todos los objetos se han establecido en señalizado. La función no modifica los estados de los objetos especificados hasta que los estados de todos los objetos se han establecido en señalizado.
Cuando el parámetro bWaitAll es FALSE, WSAWaitForMultipleEvents comprueba los identificadores de la matriz lphEvents en orden a partir del índice 0, hasta que se señala a uno de los objetos. Si se señalizan varios objetos, la función devuelve el índice del primer identificador de la matriz lphEvents cuyo objeto se señalizó.
Esta función también se usa para realizar una espera alertable estableciendo el parámetro fAlertable en TRUE. Esto permite que la función devuelva cuando el sistema ejecuta una rutina de finalización de E/S mediante el subproceso que realiza la llamada.
Un subproceso debe estar en un estado de espera alertable para que el sistema ejecute rutinas de finalización de E/S (llamadas de procedimiento asincrónico o API). Por lo tanto, si una aplicación llama a WSAWaitForMultipleEvents cuando hay operaciones asincrónicas pendientes que tienen rutinas de finalización de E/S y el parámetro fAlertable es FALSE, esas rutinas de finalización de E/S no se ejecutarán aunque se completen esas operaciones de E/S.
Si el parámetro fAlertable es TRUE y se completa una de las operaciones pendientes, se ejecuta APC y WSAWaitForMultipleEvents devolverá WSA_IO_COMPLETION. El evento pendiente aún no está señalado. La aplicación debe llamar de nuevo a la función WSAWaitForMultipleEvents .
Las aplicaciones que requieren un estado de espera alertable sin esperar a que se señale ningún objeto de evento deben usar la función SleepEx de Windows.
La implementación actual de WSAWaitForMultipleEvents llama a la función WaitForMultipleObjectsEx .
Código de ejemplo
En el ejemplo de código siguiente se muestra cómo usar la función 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: esta función es compatible con las aplicaciones de Windows Phone Store en Windows Phone 8 y versiones posteriores.
Windows 8.1 y Windows Server 2012 R2: esta función es compatible con las aplicaciones de la Tienda Windows en Windows 8.1, Windows Server 2012 R2 y versiones posteriores.
Requisitos
Cliente mínimo compatible | Windows 8.1, Windows Vista [aplicaciones de escritorio | Aplicaciones para UWP] |
Servidor mínimo compatible | Windows Server 2003 [aplicaciones de escritorio | aplicaciones para UWP] |
Plataforma de destino | Windows |
Encabezado | winsock2.h |
Library | Ws2_32.lib |
Archivo DLL | Ws2_32.dll |