Funzione WSAWaitForMultipleEvents (winsock2.h)
La funzione WSAWaitForMultipleEvents restituisce quando uno o tutti gli oggetti evento specificati si trovano nello stato segnalato, quando l'intervallo di timeout scade o quando viene eseguita una routine di completamento di I/O.
Sintassi
DWORD WSAAPI WSAWaitForMultipleEvents(
[in] DWORD cEvents,
[in] const WSAEVENT *lphEvents,
[in] BOOL fWaitAll,
[in] DWORD dwTimeout,
[in] BOOL fAlertable
);
Parametri
[in] cEvents
Numero di handle di oggetti evento nella matrice a cui punta lphEvents. Il numero massimo di handle di oggetti evento è WSA_MAXIMUM_WAIT_EVENTS. È necessario specificare uno o più eventi.
[in] lphEvents
Puntatore a una matrice di handle di oggetti evento. La matrice può contenere handle di oggetti di tipi diversi. Potrebbe non contenere più copie dello stesso handle se il parametro fWaitAll è impostato su TRUE. Se uno di questi handle viene chiuso mentre l'attesa è ancora in sospeso, il comportamento di WSAWaitForMultipleEvents non è definito.
Gli handle devono avere il diritto di accesso SYNC . Per altre informazioni, vedere Diritti di accesso standard.
[in] fWaitAll
Valore che specifica il tipo di attesa. Se TRUE, la funzione restituisce quando viene segnalato lo stato di tutti gli oggetti nella matrice lphEvents . Se FALSE, la funzione restituisce quando viene segnalato uno degli oggetti evento. In quest'ultimo caso, il valore restituito meno WSA_WAIT_EVENT_0 indica l'indice dell'oggetto evento il cui stato ha causato la restituzione della funzione. Se durante la chiamata viene segnalato più di un oggetto evento, questo è l'indice della matrice all'oggetto evento segnalato con il valore di indice più piccolo di tutti gli oggetti evento segnalati.
[in] dwTimeout
Intervallo di timeout, in millisecondi. WSAWaitForMultipleEvents restituisce se l'intervallo di timeout scade, anche se le condizioni specificate dal parametro fWaitAll non sono soddisfatte. Se il parametro dwTimeout è zero, WSAWaitForMultipleEvents verifica lo stato degli oggetti evento specificati e restituisce immediatamente. Se dwTimeout è WSA_INFINITE, WSAWaitForMultipleEvents attende per sempre; ovvero, l'intervallo di timeout non scade mai.
[in] fAlertable
Valore che specifica se il thread viene inserito in uno stato di attesa avvisabile in modo che il sistema possa eseguire routine di completamento di I/O. Se TRUE, il thread viene inserito in uno stato di attesa avvisabile e WSAWaitForMultipleEvents può restituire quando il sistema esegue una routine di completamento di I/O. In questo caso, WSA_WAIT_IO_COMPLETION viene restituito e l'evento in attesa non viene ancora segnalato. L'applicazione deve chiamare nuovamente la funzione WSAWaitForMultipleEvents . Se FALSE, il thread non viene inserito in uno stato di attesa avvisabile e le routine di completamento di I/O non vengono eseguite.
Valore restituito
Se la funzione WSAWaitForMultipleEvents ha esito positivo, il valore restituito al termine dell'operazione è uno dei valori seguenti.
Valore restituito | Significato |
---|---|
|
Se il parametro fWaitAll è TRUE, il valore restituito indica che tutti gli oggetti evento specificati vengono segnalati.
Se il parametro fWaitAll è FALSE, il valore restituito meno WSA_WAIT_EVENT_0 indica l'indice della matrice lphEvents dell'oggetto evento segnalato che ha soddisfatto l'attesa. Se durante la chiamata viene segnalato più di un oggetto evento, il valore restituito indica l'indice della matrice lphEvents dell'oggetto evento segnalato con il valore di indice più piccolo di tutti gli oggetti evento segnalati. |
|
L'attesa è stata terminata da una o più routine di completamento di I/O eseguite. L'evento in attesa non è ancora segnalato. L'applicazione deve chiamare nuovamente la funzione WSAWaitForMultipleEvents . Questo valore restituito può essere restituito solo se il parametro fAlertable è TRUE. |
|
L'intervallo di timeout trascorso e le condizioni specificate dal parametro fWaitAll non sono state soddisfatte. Non sono state eseguite routine di completamento di I/O. |
Se la funzione WSAWaitForMultipleEvents ha esito negativo, il valore restituito è WSA_WAIT_FAILED. La tabella seguente elenca i valori che possono essere usati con WSAGetLastError per ottenere informazioni di errore estese.
Codice di errore | Significato |
---|---|
WSANOTINITIALISED | Prima di usare questa funzione, è necessario eseguire una chiamata WSAStartup riuscita. |
WSAENETDOWN | Il sottosistema di rete non è riuscito. |
WSAEINPROGRESS | Una chiamata windows Sockets 1.1 bloccata è in corso oppure il provider di servizi sta ancora elaborando una funzione di callback. |
WSA_NOT_ENOUGH_MEMORY | Memoria insufficiente disponibile per completare l'operazione. |
WSA_INVALID_HANDLE | Uno o più valori della matrice lphEvents non è un handle dell'oggetto evento valido. |
WSA_INVALID_PARAMETER | Il parametro cEvents non contiene un conteggio di handle valido. |
Commenti
La funzione WSAWaitForMultipleEvents determina se sono stati soddisfatti i criteri di attesa. Se i criteri non sono stati soddisfatti, il thread chiamante entra nello stato di attesa. Non usa tempo di processore in attesa dei criteri da soddisfare.
La funzione WSAWaitForMultipleEvents restituisce quando uno o tutti gli oggetti specificati si trovano nello stato segnalato o quando l'intervallo di timeout viene trascorso.
Quando il parametro bWaitAll è TRUE, l'operazione di attesa viene completata solo quando gli stati di tutti gli oggetti sono stati impostati su segnalato. La funzione non modifica gli stati degli oggetti specificati fino a quando gli stati di tutti gli oggetti sono stati impostati per segnalare.
Quando il parametro bWaitAll è FALSE, WSAWaitForMultipleEvents controlla gli handle nella matrice lphEvents in ordine a partire dall'indice 0, fino a quando non viene segnalato uno degli oggetti. Se più oggetti vengono segnalati, la funzione restituisce l'indice del primo handle nella matrice lphEvents l cui oggetto è stato segnalato.
Questa funzione viene usata anche per eseguire un'attesa avvisabile impostando il parametro fAlertable su TRUE. Ciò consente alla funzione di restituire quando il sistema esegue una routine di completamento di I/O tramite il thread chiamante.
Un thread deve trovarsi in uno stato di attesa avvisabile per consentire al sistema di eseguire routine di completamento di I/O (chiamate di routine asincrone o API). Quindi, se un'applicazione chiama WSAWaitForMultipleEvents quando sono presenti operazioni asincrone in sospeso con routine di completamento di I/O e il parametro fAlertable è FALSE, tali routine di completamento di I/O non verranno eseguite anche se tali operazioni di I/O vengono completate.
Se il parametro fAlertable è TRUE e una delle operazioni in sospeso viene completata, l'APC viene eseguito e WSAWaitForMultipleEvents restituirà WSA_IO_COMPLETION. L'evento in sospeso non viene ancora segnalato. L'applicazione deve chiamare nuovamente la funzione WSAWaitForMultipleEvents .
Le applicazioni che richiedono uno stato di attesa avvisabile senza attendere che tutti gli oggetti evento vengano segnalati devono usare la funzione Windows SleepEx .
L'implementazione corrente di WSAWaitForMultipleEvents chiama la funzione WaitForMultipleObjectsEx .
Codice di esempio
Nell'esempio di codice seguente viene illustrato come usare la funzione 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: questa funzione è supportata per le app Windows Phone Store in Windows Phone 8 e versioni successive.
Windows 8.1 e Windows Server 2012 R2: questa funzione è supportata per le app di Windows Store in Windows 8.1, Windows Server 2012 R2 e versioni successive.
Requisiti
Client minimo supportato | Windows 8.1, Windows Vista [app desktop | App UWP] |
Server minimo supportato | Windows Server 2003 [app desktop | App UWP] |
Piattaforma di destinazione | Windows |
Intestazione | winsock2.h |
Libreria | Ws2_32.lib |
DLL | Ws2_32.dll |