Funzione WSAAsyncSelect (winsock.h)

[La funzione WSAAsyncSelect è disponibile per l'uso nei sistemi operativi specificati nella sezione Requisiti. È possibile che in versioni successive sia stata modificata o non sia più disponibile. Anziché usare I/O in stile Select, usare oggetti di I/O sovrapposti e eventi con WinSock2.

La funzione WSAAsyncSelect richiede la notifica basata su messaggi di Windows per gli eventi di rete per un socket.

Sintassi

int WSAAsyncSelect(
  [in] SOCKET s,
  [in] HWND   hWnd,
  [in] u_int  wMsg,
  [in] long   lEvent
);

Parametri

[in] s

Descrittore che identifica il socket per cui è necessaria la notifica degli eventi.

[in] hWnd

Handle che identifica la finestra che riceverà un messaggio quando si verifica un evento di rete.

[in] wMsg

Messaggio da ricevere quando si verifica un evento di rete.

[in] lEvent

Maschera bit che specifica una combinazione di eventi di rete in cui l'applicazione è interessato.

Valore restituito

Se la funzione WSAAsyncSelect ha esito positivo, il valore restituito è zero, purché la dichiarazione di interesse dell'applicazione nel set di eventi di rete abbia avuto esito positivo. In caso contrario, il valore SOCKET_ERROR viene restituito e un numero di errore specifico può essere recuperato chiamando WSAGetLastError.

Codice di errore Significato
WSANOTINITIALISED
Prima di usare questa funzione, è necessario eseguire una chiamata WSAStartup riuscita.
WSAENETDOWN
Il sottosistema di rete non è riuscito.
WSAEINVAL
Uno dei parametri specificati non è valido, ad esempio l'handle della finestra che non fa riferimento a una finestra esistente o il socket specificato è in uno stato non valido.
WSAEINPROGRESS
Una chiamata windows Sockets 1.1 bloccata è in corso oppure il provider di servizi sta ancora elaborando una funzione di callback.
WSAENOTSOCK
Il descrittore non è un socket.
 

È possibile impostare codici di errore aggiuntivi quando una finestra dell'applicazione riceve un messaggio. Questo codice di errore viene estratto dall'oggetto lParam nel messaggio di risposta usando la macro WSAGETSELECTERROR . I codici di errore possibili per ogni evento di rete sono elencati nella tabella seguente.

Evento: FD_CONNECT

Codice di errore Significato
WSAEAFNOSUPPORT Impossibile utilizzare gli indirizzi della famiglia specificata con questo socket.
WSAECONNREFUSED Il tentativo di connessione è stato rifiutato.
WSAENETUNREACH Impossibile raggiungere la rete da questo host in questo momento.
WSAEFAULT Il parametro namelen non è valido.
WSAEINVAL Il socket è già associato a un indirizzo.
WSAEISCONN Il socket è già connesso.
WSAEMFILE Non sono disponibili altri descrittori di file.
WSAENOBUFS Nessuno spazio di buffer disponibile. Impossibile connettere il socket.
WSAENOTCONN Il socket non è connesso.
WSAETIMEDOUT Tentare di connettersi senza stabilire una connessione.
 

Evento: FD_CLOSE

Codice di errore Significato
WSAENETDOWN Il sottosistema di rete non è riuscito.
WSAECONNRESET La connessione è stata reimpostata dal lato remoto.
WSAECONNABORTED La connessione è stata terminata a causa di un timeout o di un altro errore.
 
Codice di errore Significato
WSAENETDOWN Il sottosistema di rete non è riuscito.
 

Evento: FD_ROUTING_INTERFACE_CHANGE

Codice di errore Significato
WSAENETUNREACH La destinazione specificata non è più raggiungibile.
WSAENETDOWN Il sottosistema di rete non è riuscito.

Commenti

La funzione WSAAsyncSelect viene usata per richiedere che WS2_32.DLL deve inviare un messaggio alla finestra hWnd quando rileva qualsiasi evento di rete specificato dal parametro lEvent . Il messaggio che deve essere inviato viene specificato dal parametro wMsg . Il socket per cui è necessaria la notifica è identificato dal parametro s .

La funzione WSAAsyncSelect imposta automaticamente socket s su modalità nonblocking, indipendentemente dal valore di lEvent. Per impostare il socket sulla modalità di blocco, è prima necessario cancellare il record di eventi associato al socket s tramite una chiamata a WSAAsyncSelect con lEvent impostato su zero. È quindi possibile chiamare ioctlsocket o WSAIoctl per impostare il socket indietro sulla modalità di blocco. Per altre informazioni su come impostare il socket nonblocking sulla modalità di blocco, vedere le funzioni ioctlsocket e WSAIoctl .

Il parametro lEvent viene costruito usando l'operatore OR bit per bit con qualsiasi valore elencato nella tabella seguente.

Valore Significato
FD_READ Impostare per ricevere una notifica di idoneità alla lettura.
FD_WRITE Vuole ricevere una notifica di idoneità per la scrittura.
FD_OOB Vuole ricevere una notifica dell'arrivo dei dati OOB.
FD_ACCEPT Vuole ricevere una notifica delle connessioni in ingresso.
FD_CONNECT Vuole ricevere una notifica dell'operazione di join completa o multipoint.
FD_CLOSE Vuole ricevere una notifica di chiusura del socket.
FD_QOS Vuole ricevere la notifica delle modifiche di qualità del servizio (QoS) del socket.
FD_GROUP_QOS Vuole ricevere la notifica delle modifiche QoS (Quality of Service) del gruppo socket (riservate per un uso futuro con i gruppi socket). Riservato.
FD_ROUTING_INTERFACE_CHANGE Vuole ricevere la notifica delle modifiche dell'interfaccia di routing per le destinazioni specificate.
FD_ADDRESS_LIST_CHANGE Vuole ricevere la notifica delle modifiche all'elenco di indirizzi locali per la famiglia di protocolli socket.
 

L'emissione di un WSAAsyncSelect per un socket annulla qualsiasi WSAAsyncSelect precedente o WSAEventSelect per lo stesso socket. Ad esempio, per ricevere una notifica sia per la lettura che per la scrittura, l'applicazione deve chiamare WSAAsyncSelect con FD_READ e FD_WRITE, come indicato di seguito:

rc = WSAAsyncSelect(s, hWnd, wMsg, FD_READ|FD_WRITE);

Non è possibile specificare messaggi diversi per eventi diversi. Il codice seguente non funzionerà; la seconda chiamata annulla gli effetti del primo e solo gli eventi FD_WRITE verranno segnalati con il messaggio wMsg2:

rc = WSAAsyncSelect(s, hWnd, wMsg1, FD_READ);
rc = WSAAsyncSelect(s, hWnd, wMsg2, FD_WRITE);

Per annullare tutte le notifiche che indicano che Windows Sockets non deve inviare altri messaggi correlati agli eventi di rete nel socket, lEvent è impostato su zero.

rc = WSAAsyncSelect(s, hWnd, 0, 0);

Anche se WSAAsyncSelect disabilita immediatamente la registrazione dei messaggi di evento per il socket in questa istanza, è possibile che i messaggi possano essere in attesa nella coda dei messaggi dell'applicazione. Pertanto, l'applicazione deve essere preparata per ricevere messaggi di eventi di rete anche dopo l'annullamento. La chiusura di un socket con closesocket annulla anche l'invio di messaggi WSAAsyncSelect , ma lo stesso avviso sui messaggi nella coda si applica ancora.

Il socket creato dalla funzione accept ha le stesse proprietà del socket di ascolto usato per accettarlo. Di conseguenza, gli eventi WSAAsyncSelect impostati per il socket di ascolto si applicano anche al socket accettato. Ad esempio, se un socket in ascolto include eventi WSAAsyncSelectFD_ACCEPT, FD_READ e FD_WRITE, qualsiasi socket accettato in tale socket in ascolto avrà anche eventi FD_ACCEPT, FD_READ e FD_WRITE con lo stesso valore wMsg usato per i messaggi. Se si desiderano eventi o wMsg diversi, l'applicazione deve chiamare WSAAsyncSelect, passando il socket accettato e i nuovi dati desiderati.

Quando si verifica uno degli eventi di rete designati nel socket specificato, la finestra dell'applicazione hWnd riceve il messaggio wMsg. Il parametro wParam identifica il socket in cui si è verificato un evento di rete. La parola bassa di lParam specifica l'evento di rete che si è verificato. La parola alta di lParam contiene qualsiasi codice di errore. Il codice di errore è qualsiasi errore definito in Winsock2.h.

Nota Al ricevimento di un messaggio di notifica dell'evento, la funzione WSAGetLastError non può essere usata per controllare il valore di errore perché il valore di errore restituito può essere diverso dal valore nella parola alta di lParam.
 
I codici di errore e di evento possono essere estratti da lParam usando le macro WSAGETSELECTERROR e WSAGETSELECTEVENT, definite in Winsock2.h come:
#include <windows.h>

#define WSAGETSELECTEVENT(lParam)       LOWORD(lParam)
#define WSAGETSELECTERROR(lParam)       HIWORD(lParam)

L'uso di queste macro consente di ottimizzare la portabilità del codice sorgente per l'applicazione.

I possibili codici di evento di rete che è possibile restituire sono elencati nella tabella seguente.

Valore Significato
FD_READ Socket pronto per la lettura.
FD_WRITE Socket pronto per la scrittura.
FD_OOB Dati OOB pronti per la lettura nel socket
FD_ACCEPT Socket pronto per l'accettazione di una nuova connessione in ingresso.
FD_CONNECT Operazione di connessione o join multipoint avviata nel socket completato .
FD_CLOSE La connessione identificata dal socket s è stata chiusa.
FD_QOS La qualità del servizio associata al socket s è stata modificata.
FD_GROUP_QOS Riservato. La qualità del servizio associata al gruppo di socket a cui appartiene è stata modificata (riservata per l'uso futuro con i gruppi di socket).
FD_ROUTING_INTERFACE_CHANGE L'interfaccia locale che deve essere utilizzata per l'invio alla destinazione specificata è stata modificata.
FD_ADDRESS_LIST_CHANGE Elenco di indirizzi della famiglia di protocolli socket in cui il client dell'applicazione può eseguire l'associazione è stato modificato.
 

Anche se WSAAsyncSelect può essere chiamato con interesse per più eventi, la finestra dell'applicazione riceverà un singolo messaggio per ogni evento di rete.

Come nel caso della funzione select , WSAAsyncSelect verrà spesso usato per determinare quando un'operazione di trasferimento dati (invio o recv) può essere rilasciata con l'aspettativa di esito positivo immediato. Tuttavia, un'applicazione affidabile deve essere preparata per la possibilità che possa ricevere un messaggio e inviare una chiamata di Windows Sockets 2 che restituisce immediatamente WSAEWOULDBLOCK . Ad esempio, è possibile eseguire la sequenza di eventi seguente:

  1. I dati arrivano sul socket s; Messaggi WSAAsyncSelect di Windows Sockets 2
  2. L'applicazione elabora altri messaggi
  3. Durante l'elaborazione, l'applicazione emette un e ioctlsocket(s, FIONREAD...) nota che sono presenti dati pronti per la lettura
  4. L'applicazione rilascia un oggetto recv(s,...) per leggere i dati
  5. Cicli dell'applicazione per elaborare il messaggio successivo, raggiungendo infine il messaggio WSAAsyncSelect che indica che i dati sono pronti per la lettura
  6. recv(s,...)Problemi dell'applicazione , che hanno esito negativo con l'errore WSAEWOULDBLOCK.
Sono possibili anche altre sequenze.

Il WS2_32.DLL non inonda continuamente un'applicazione con messaggi per un determinato evento di rete. Dopo aver inviato correttamente la notifica di un determinato evento a una finestra dell'applicazione, non verranno inviati altri messaggi per tale evento di rete alla finestra dell'applicazione finché l'applicazione non effettua la chiamata di funzione che riabilita in modo implicito la notifica di tale evento di rete.

Evento Funzione Reenabling
FD_READ recv, recvfrom, WSARecv o WSARecvFrom.
FD_WRITE sendto, sendto, WSASend o WSASendTo.
FD_OOB recv, recvfrom, WSARecv o WSARecvFrom.
FD_ACCEPT accept o WSAAccept a meno che il codice di errore non sia WSATRY_AGAIN che indica che la funzione della condizione ha restituito CF_DEFER.
FD_CONNECT Nessuno.
FD_CLOSE Nessuno.
FD_QOS WSAIoctl con il comando SIO_GET_QOS.
FD_GROUP_QOS Riservato. WSAIoctl con il comando SIO_GET_GROUP_QOS (riservato per uso futuro con i gruppi di socket).
FD_ROUTING_INTERFACE_CHANGE WSAIoctl con il comando SIO_ROUTING_INTERFACE_CHANGE.
FD_ADDRESS_LIST_CHANGE WSAIoctl con il comando SIO_ADDRESS_LIST_CHANGE.
 

Qualsiasi chiamata alla routine di ripetizione, anche quella che ha esito negativo, comporta la ripetizione della registrazione dei messaggi per l'evento pertinente.

Per gli eventi di FD_READ, FD_OOB e FD_ACCEPT , la registrazione dei messaggi viene attivata a livello. Ciò significa che se la routine di ripetizione viene chiamata e la condizione pertinente viene comunque soddisfatta dopo la chiamata, viene inviato un messaggio WSAAsyncSelect all'applicazione. Ciò consente a un'applicazione di essere guidata dagli eventi e di non preoccuparsi della quantità di dati che arrivano in qualsiasi momento. Considerare la sequenza seguente:

  1. Lo stack di trasporto di rete riceve 100 byte di dati nel socket s e fa in modo che Windows Sockets 2 pubblichi un messaggio di FD_READ .
  2. I problemi dell'applicazione rev( s, buffptr, 50, 0) per leggere 50 byte.
  3. Viene pubblicato un altro messaggio FD_READ perché sono ancora presenti dati da leggere.
Con questa semantica, un'applicazione non deve leggere tutti i dati disponibili in risposta a un messaggio di FD_READ. In risposta a ogni messaggio di FD_READ è appropriato un singolo recv in risposta a ogni messaggio di FD_READ. Se un'applicazione genera più chiamate recv in risposta a un singolo FD_READ, può ricevere più messaggi FD_READ . Un'applicazione di questo tipo può richiedere la disabilitazione di FD_READ messaggi prima di avviare le chiamate recv chiamando WSAAsyncSelect con l'evento FD_READ non impostato.

Gli eventi FD_QOS e FD_GROUP_QOS vengono considerati attivati da edge. Un messaggio verrà inviato esattamente una volta quando si verifica una modifica della qualità del servizio. Altri messaggi non saranno imminenti finché il provider non rileverà un'ulteriore modifica della qualità del servizio o l'applicazione rinegozia la qualità del servizio per il socket.

Il messaggio FD_ROUTING_INTERFACE_CHANGE viene inviato quando l'interfaccia locale da usare per raggiungere la destinazione specificata in WSAIoctl con SIO_ROUTING_INTERFACE_CHANGE modifiche dopo l'emissione di tale IOCTL.

Il messaggio di FD_ADDRESS_LIST_CHANGE viene inviato quando l'elenco di indirizzi a cui l'applicazione può associare le modifiche dopo l'emissione di WSAIoctl con SIO_ADDRESS_LIST_CHANGE.

Se si verifica un evento quando l'applicazione chiama WSAAsyncSelect o quando viene chiamata la funzione di reenabling, viene inviato un messaggio in base alle esigenze. Si consideri, ad esempio, la sequenza seguente:

  1. Un'applicazione chiama listen.
  2. Viene ricevuta una richiesta di connessione, ma non ancora accettata.
  3. L'applicazione chiama WSAAsyncSelect specificando che richiede la ricezione di FD_ACCEPT messaggi per il socket. A causa della persistenza degli eventi, Windows Sockets 2 pubblica immediatamente un messaggio FD_ACCEPT .

L'evento FD_WRITE viene gestito in modo leggermente diverso. Un messaggio di FD_WRITE viene inviato quando un socket viene connesso per la prima volta con connessione o WSAConnect (dopo FD_CONNECT, se anche registrato) o accettato con accept o WSAAccept e quindi dopo che un'operazione di invio ha esito negativo con WSAEWOULDBLOCK e lo spazio del buffer diventa disponibile. Pertanto, un'applicazione può presupporre che gli invii siano possibili a partire dal primo messaggio FD_WRITE e duraturo fino a quando un invio non restituisce WSAEWOULDBLOCK. Dopo un errore di questo tipo, l'applicazione riceverà una notifica che indica che gli invii sono nuovamente possibili con un messaggio di FD_WRITE .

L'evento FD_OOB viene usato solo quando un socket è configurato per ricevere i dati OOB separatamente. Se il socket è configurato per ricevere dati OOB inline, i dati OOB (accelerati) vengono considerati come dati normali e l'applicazione deve registrare un interesse e riceverà, FD_READ eventi, non FD_OOB eventi. Un'applicazione può impostare o controllare il modo in cui gestire i dati OOB usando setsockopt o getsockopt per l'opzione SO_OOBINLINE.

Il codice di errore in un messaggio di FD_CLOSE indica se la chiusura del socket è stata normale o interrotta. Se il codice di errore è zero, la chiusura era normale; se il codice di errore è WSAECONNRESET, il circuito virtuale del socket è stato reimpostato. Questo vale solo per i socket orientati alla connessione, ad esempio SOCK_STREAM.

Il messaggio FD_CLOSE viene inviato quando viene ricevuta un'indicazione di chiusura per il circuito virtuale corrispondente al socket. In termini TCP, ciò significa che il FD_CLOSE viene registrato quando la connessione entra negli stati TIME WAIT o CLOSE WAIT. Ciò risulta dall'estremità remota che esegue un arresto sul lato di invio o un closesocket. FD_CLOSE devono essere pubblicati solo dopo che tutti i dati vengono letti da un socket, ma un'applicazione deve verificare la presenza di dati rimanenti al ricevimento di FD_CLOSE per evitare eventuali perdite di dati.

Tenere presente che l'applicazione riceverà solo un messaggio di FD_CLOSE per indicare la chiusura di un circuito virtuale e solo quando tutti i dati ricevuti sono stati letti se si tratta di una chiusura normale. Non riceverà un messaggio FD_READ per indicare questa condizione.

Il messaggio FD_QOS o FD_GROUP_QOS viene inviato quando un parametro nella specifica del flusso associato al socket s o al gruppo di socket a cui appartiene è stato modificato, rispettivamente. Le applicazioni devono usare WSAIoctl con il comando SIO_GET_QOS o SIO_GET_GROUP_QOS per ottenere rispettivamente la qualità corrente del servizio per socket s o per il gruppo di socket.

Anche gli eventi FD_ROUTING_INTERFACE_CHANGE e FD_ADDRESS_LIST_CHANGE vengono considerati attivati da edge. Un messaggio verrà inviato esattamente una volta quando si verifica una modifica dopo che l'applicazione ha richiesto la notifica inviando WSAIoctl con SIO_ROUTING_INTERFACE_CHANGE o SIO_ADDRESS_LIST_CHANGE in modo corrispondente. Altri messaggi non saranno imminenti fino a quando l'applicazione non esegue nuovamente il codice IOCTL e viene rilevata un'altra modifica perché l'IOCTL è stato rilasciato.

Ecco un riepilogo di eventi e condizioni per ogni messaggio di notifica asincrono.

  • FD_READ:
    1. Quando viene chiamato WSAAsyncSelect , se sono attualmente disponibili dati da ricevere.
    2. Quando arrivano i dati, se FD_READ non è già pubblicato.
    3. Dopo aver chiamato recv o recvfrom , con o senza MSG_PEEK), se i dati sono ancora disponibili per la ricezione.
      Nota Quando setockopt SO_OOBINLINE è abilitato, i dati includono sia i dati normali che i dati OOB nelle istanze indicate in precedenza.
       
  • FD_WRITE:
    1. Quando WSAAsyncSelect viene chiamato, se è possibile inviare oinviare .
    2. Dopo la connessione o l'accettazione viene chiamata, quando viene stabilita la connessione.
    3. Dopo l'invio o l'invio ha esito negativo con WSAEWOULDBLOCK, è probabile che l'invio o l'invio abbia esito positivo.
    4. Dopo l'associazione su un socket senza connessione. FD_WRITE può verificarsi o meno in questo momento (dipendente dall'implementazione). In ogni caso, un socket senza connessione è sempre scrivibile immediatamente dopo un'operazione di associazione .
  • FD_OOB: valido solo quando setockopt SO_OOBINLINE è disabilitato (impostazione predefinita).
    1. Quando WSAAsyncSelect viene chiamato, se sono attualmente disponibili dati OOB da ricevere con il flag di MSG_OOB.
    2. Quando arrivano i dati OOB, se FD_OOB non è già stato pubblicato.
    3. Dopo aver chiamato recv o recvfrom con o senza flag MSG_OOB, se i dati OOB sono ancora disponibili per la ricezione.
  • FD_ACCEPT:
    1. Quando WSAAsyncSelect viene chiamato, se è attualmente disponibile una richiesta di connessione da accettare.
    2. Quando arriva una richiesta di connessione, se FD_ACCEPT non è già stata inviata.
    3. Dopo l'accettazione chiamata, se è disponibile un'altra richiesta di connessione da accettare.
  • FD_CONNECT:
    1. Quando WSAAsyncSelect viene chiamato, se è attualmente stabilita una connessione.
    2. Dopo aver chiamato la connessione , quando viene stabilita la connessione, anche quando la connessione ha esito positivo immediatamente, come avviee in genere con un socket di datagrammi.
    3. Dopo aver chiamato WSAJoinLeaf, al termine dell'operazione di join.
    4. Dopo la connessione, WSAConnect o WSAJoinLeaf è stato chiamato con un socket non bloccato orientato alla connessione. L'operazione iniziale restituita con un errore specifico di WSAEWOULDBLOCK, ma l'operazione di rete è andata avanti. Se l'operazione ha esito positivo o negativo, quando il risultato è stato determinato, FD_CONNECT si verifica. Il client deve controllare il codice di errore per determinare se il risultato è riuscito o negativo.
  • FD_CLOSE: solo sui socket orientati alla connessione (ad esempio, SOCK_STREAM)
    1. Quando WSAAsyncSelect viene chiamato, se la connessione socket è stata chiusa.
    2. Dopo la chiusura normale avviata dal sistema remoto, quando non sono disponibili dati attualmente disponibili per la ricezione (tenere presente che, se i dati sono stati ricevuti ed è in attesa di essere letti quando il sistema remoto avvia una chiusura normale, il FD_CLOSE non viene recapitato fino a quando non vengono letti tutti i dati in sospeso).
    3. Dopo che il sistema locale avvia una chiusura normale con arresto e sistema remoto ha risposto con la notifica "Fine dei dati", ad esempio TCP FIN, quando non sono attualmente disponibili dati per la ricezione.
    4. Quando il sistema remoto termina la connessione (ad esempio, TCP RST inviato) e lParam conterrà il valore di errore WSAECONNRESET .
      NotaFD_CLOSE non viene pubblicato dopo la chiamata a closesocket .
       
  • FD_QOS:
    1. Quando WSAAsyncSelect viene chiamato, se la qualità del servizio associata al socket è stata modificata.
    2. Dopo WSAIoctl con SIO_GET_QOS chiamato, quando viene modificata la qualità del servizio.
  • FD_GROUP_QOS: riservato.
  • FD_ROUTING_INTERFACE_CHANGE:
    • Dopo WSAIoctl con SIO_ROUTING_INTERFACE_CHANGE chiamata, quando viene modificata l'interfaccia locale da usare per raggiungere la destinazione specificata in IOCTL.
  • FD_ADDRESS_LIST_CHANGE:
    • Dopo WSAIoctl con SIO_ADDRESS_LIST_CHANGE chiamato, quando l'elenco di indirizzi locali a cui l'applicazione può associare le modifiche.

Requisiti

Requisito Valore
Client minimo supportato Windows 2000 Professional [solo app desktop]
Server minimo supportato Windows 2000 Server [solo app desktop]
Piattaforma di destinazione Windows
Intestazione winsock.h (include Winsock2.h)
Libreria Ws2_32.lib
DLL Ws2_32.dll

Vedi anche

WSAEventSelect

Funzioni Winsock

Informazioni di riferimento su Winsock

select