Função WSAWaitForMultipleEvents (winsock2.h)
A função WSAWaitForMultipleEvents retorna quando um ou todos os objetos de evento especificados estão no estado sinalizado, quando o intervalo de tempo limite expira ou quando uma rotina de conclusão de E/S é executada.
Sintaxe
DWORD WSAAPI WSAWaitForMultipleEvents(
[in] DWORD cEvents,
[in] const WSAEVENT *lphEvents,
[in] BOOL fWaitAll,
[in] DWORD dwTimeout,
[in] BOOL fAlertable
);
Parâmetros
[in] cEvents
O número de identificadores de objeto de evento na matriz apontada por lphEvents. O número máximo de identificadores de objeto de evento é WSA_MAXIMUM_WAIT_EVENTS. Um ou mais eventos devem ser especificados.
[in] lphEvents
Um ponteiro para uma matriz de identificadores de objeto de evento. A matriz pode conter identificadores de objetos de diferentes tipos. Ele pode não conter várias cópias do mesmo identificador se o parâmetro fWaitAll estiver definido como TRUE. Se um desses identificadores for fechado enquanto a espera ainda estiver pendente, o comportamento de WSAWaitForMultipleEvents será indefinido.
Os identificadores devem ter o direito de acesso SYNCHRONIZE . Para obter mais informações, consulte Direitos de Acesso Padrão.
[in] fWaitAll
Um valor que especifica o tipo de espera. Se TRUE, a função retornará quando o estado de todos os objetos na matriz lphEvents for sinalizado. Se FALSE, a função retornará quando qualquer um dos objetos de evento for sinalizado. No último caso, o valor retornado menos WSA_WAIT_EVENT_0 indica o índice do objeto de evento cujo estado fez com que a função retornasse. Se mais de um objeto de evento tiver sido sinalizado durante a chamada, esse será o índice de matriz para o objeto de evento sinalizado com o menor valor de índice de todos os objetos de evento sinalizados.
[in] dwTimeout
O intervalo de tempo limite em milissegundos. WSAWaitForMultipleEvents retornará se o intervalo de tempo limite expirar, mesmo que as condições especificadas pelo parâmetro fWaitAll não sejam atendidas. Se o parâmetro dwTimeout for zero, WSAWaitForMultipleEvents testará o estado dos objetos de evento especificados e retornará imediatamente. Se dwTimeout for WSA_INFINITE, WSAWaitForMultipleEvents aguardará para sempre; ou seja, o intervalo de tempo limite nunca expira.
[in] fAlertable
Um valor que especifica se o thread é colocado em um estado de espera alertável para que o sistema possa executar rotinas de conclusão de E/S. Se TRUE, o thread será colocado em um estado de espera alertável e WSAWaitForMultipleEvents poderá retornar quando o sistema executar uma rotina de conclusão de E/S. Nesse caso, WSA_WAIT_IO_COMPLETION é retornado e o evento que estava sendo aguardado ainda não é sinalizado. O aplicativo deve chamar a função WSAWaitForMultipleEvents novamente. Se FALSE, o thread não será colocado em um estado de espera alertável e as rotinas de conclusão de E/S não serão executadas.
Valor retornado
Se a função WSAWaitForMultipleEvents for bem-sucedida, o valor retornado após o sucesso será um dos valores a seguir.
Valor Retornado | Significado |
---|---|
|
Se o parâmetro fWaitAll for TRUE, o valor retornado indicará que todos os objetos de evento especificados serão sinalizados.
Se o parâmetro fWaitAll for FALSE, o valor retornado menos WSA_WAIT_EVENT_0 indicará o índice de matriz lphEvents do objeto de evento sinalizado que atendeu à espera. Se mais de um objeto de evento tiver sido sinalizado durante a chamada, o valor retornado indicará o índice de matriz lphEvents do objeto de evento sinalizado com o menor valor de índice de todos os objetos de evento sinalizados. |
|
A espera foi encerrada por uma ou mais rotinas de conclusão de E/S que foram executadas. O evento que estava sendo aguardado ainda não é sinalizado. O aplicativo deve chamar a função WSAWaitForMultipleEvents novamente. Esse valor retornado só poderá ser retornado se o parâmetro fAlertable for TRUE. |
|
O intervalo de tempo limite decorrido e as condições especificadas pelo parâmetro fWaitAll não foram atendidas. Nenhuma rotina de conclusão de E/S foi executada. |
Se a função WSAWaitForMultipleEvents falhar, o valor retornado será WSA_WAIT_FAILED. A tabela a seguir lista valores que podem ser usados com WSAGetLastError para obter informações de erro estendidas.
Código do erro | Significado |
---|---|
WSANOTINITIALISED | Uma chamada WSAStartup bem-sucedida deve ocorrer antes de usar essa função. |
WSAENETDOWN | O subsistema de rede falhou. |
WSAEINPROGRESS | Uma chamada do Windows Sockets 1.1 de bloqueio está em andamento ou o provedor de serviços ainda está processando uma função de retorno de chamada. |
WSA_NOT_ENOUGH_MEMORY | Não havia memória livre suficiente disponível para concluir a operação. |
WSA_INVALID_HANDLE | Um ou mais dos valores na matriz lphEvents não é um identificador de objeto de evento válido. |
WSA_INVALID_PARAMETER | O parâmetro cEvents não contém uma contagem de identificadores válida. |
Comentários
A função WSAWaitForMultipleEvents determina se os critérios de espera foram atendidos. Se os critérios não tiverem sido atendidos, o thread de chamada entrará no estado de espera. Ele não usa tempo de processador enquanto aguarda que os critérios sejam atendidos.
A função WSAWaitForMultipleEvents retorna quando qualquer um ou todos os objetos especificados estão no estado sinalizado ou quando o intervalo de tempo limite passa.
Quando o parâmetro bWaitAll for TRUE, a operação de espera será concluída somente quando os estados de todos os objetos tiverem sido definidos como sinalizados. A função não modifica os estados dos objetos especificados até que os estados de todos os objetos tenham sido definidos como sinalizados.
Quando o parâmetro bWaitAll é FALSE, WSAWaitForMultipleEvents verifica os identificadores na matriz lphEvents para começar com o índice 0, até que um dos objetos seja sinalizado. Se vários objetos forem sinalizados, a função retornará o índice do primeiro identificador na matriz lphEvents cujo objeto foi sinalizado.
Essa função também é usada para executar uma espera alertável definindo o parâmetro fAlertable como TRUE. Isso permite que a função retorne quando o sistema executa uma rotina de conclusão de E/S pelo thread de chamada.
Um thread deve estar em um estado de espera alertável para que o sistema execute rotinas de conclusão de E/S (APCs ou chamadas de procedimento assíncronas). Portanto, se um aplicativo chamar WSAWaitForMultipleEvents quando houver operações assíncronas pendentes que tenham rotinas de conclusão de E/S e o parâmetro fAlertable for FALSE, essas rotinas de conclusão de E/S não serão executadas mesmo se essas operações de E/S forem concluídas.
Se o parâmetro fAlertable for TRUE e uma das operações pendentes for concluída, o APC será executado e WSAWaitForMultipleEvents retornará WSA_IO_COMPLETION. O evento pendente ainda não está sinalizado. O aplicativo deve chamar a função WSAWaitForMultipleEvents novamente.
Os aplicativos que exigem um estado de espera alertável sem esperar que nenhum objeto de evento seja sinalizado devem usar a função SleepEx do Windows.
A implementação atual do WSAWaitForMultipleEvents chama a função WaitForMultipleObjectsEx .
Código de exemplo
O exemplo de código a seguir mostra como usar a função 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: essa função tem suporte para aplicativos da Windows Phone Store no Windows Phone 8 e posterior.
Windows 8.1 e Windows Server 2012 R2: essa função tem suporte para aplicativos da Windows Store em Windows 8.1, Windows Server 2012 R2 e posterior.
Requisitos
Cliente mínimo com suporte | Windows 8.1, Windows Vista [aplicativos da área de trabalho | Aplicativos UWP] |
Servidor mínimo com suporte | Windows Server 2003 [aplicativos da área de trabalho | Aplicativos UWP] |
Plataforma de Destino | Windows |
Cabeçalho | winsock2.h |
Biblioteca | Ws2_32.lib |
DLL | Ws2_32.dll |