Función WSAAsyncSelect (winsock.h)
[La función WSAAsyncSelect está disponible para su uso en los sistemas operativos especificados en la sección Requisitos. En versiones posteriores podría modificarse o no estar disponible. En lugar de usar E/S de estilo Select, use objetos de E /S superpuestos y eventos con WinSock2.
La función WSAAsyncSelect solicita la notificación basada en mensajes de Windows de eventos de red para un socket.
Sintaxis
int WSAAsyncSelect(
[in] SOCKET s,
[in] HWND hWnd,
[in] u_int wMsg,
[in] long lEvent
);
Parámetros
[in] s
Descriptor que identifica el socket para el que se requiere la notificación de eventos.
[in] hWnd
Identificador que identifica la ventana que recibirá un mensaje cuando se produzca un evento de red.
[in] wMsg
Mensaje que se va a recibir cuando se produce un evento de red.
[in] lEvent
Máscara de bits que especifica una combinación de eventos de red en los que la aplicación está interesada.
Valor devuelto
Si la función WSAAsyncSelect se realiza correctamente, el valor devuelto es cero, siempre que la declaración de interés de la aplicación en el conjunto de eventos de red se haya realizado correctamente. De lo contrario, se devuelve el valor SOCKET_ERROR y se puede recuperar un número de error específico mediante una llamada a WSAGetLastError.
Código de error | Significado |
---|---|
Debe producirse una llamada WSAStartup correcta antes de usar esta función. | |
Error en el subsistema de red. | |
Uno de los parámetros especificados no era válido, como el identificador de ventana que no hace referencia a una ventana existente o el socket especificado está en un estado no válido. | |
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. | |
El descriptor no es un socket. |
Se pueden establecer códigos de error adicionales cuando una ventana de la aplicación recibe un mensaje. Este código de error se extrae de lParam en el mensaje de respuesta mediante la macro WSAGETSELECTERROR . Los posibles códigos de error para cada evento de red se muestran en la tabla siguiente.
Evento: FD_CONNECT
Código de error | Significado |
---|---|
WSAEAFNOSUPPORT | Las direcciones de la familia especificada no se pueden usar con este socket. |
WSAECONNREFUSED | El intento de conexión se rechazó. |
WSAENETUNREACH | La red no se puede alcanzar desde este host en estos momentos. |
WSAEFAULT | El parámetro namelen no es válido. |
WSAEINVAL | El socket ya está enlazado a una dirección. |
WSAEISCONN | El socket ya está conectado. |
WSAEMFILE | No hay más descriptores de archivo disponibles. |
WSAENOBUFS | No hay espacio disponible en el búfer. El socket no se puede conectar. |
WSAENOTCONN | El socket no está conectado. |
WSAETIMEDOUT | Se ha agotado el tiempo de espera de la conexión sin poder establecer una conexión. |
Evento: FD_CLOSE
Código de error | Significado |
---|---|
WSAENETDOWN | Error en el subsistema de red. |
WSAECONNRESET | El lado remoto ha restablecido la conexión. |
WSAECONNABORTED | La conexión se finalizó debido a un tiempo de espera u otro error. |
Código de error | Significado |
---|---|
WSAENETDOWN | Error en el subsistema de red. |
Evento: FD_ROUTING_INTERFACE_CHANGE
Código de error | Significado |
---|---|
WSAENETUNREACH | El destino especificado ya no es accesible. |
WSAENETDOWN | Error en el subsistema de red. |
Comentarios
La función WSAAsyncSelect se usa para solicitar que WS2_32.DLL envíe un mensaje a la ventana hWnd cuando detecte cualquier evento de red especificado por el parámetro lEvent . El mensaje que se debe enviar se especifica mediante el parámetro wMsg . El socket para el que se requiere la notificación se identifica mediante el parámetro s .
La función WSAAsyncSelect establece automáticamente el socket s en modo sin bloqueo, independientemente del valor de lEvent. Para volver a establecer el socket en modo de bloqueo, primero es necesario borrar el registro de eventos asociado a sockets a través de una llamada a WSAAsyncSelect con lEvent establecido en cero. A continuación, puede llamar a ioctlsocket o WSAIoctl para volver a establecer el socket en modo de bloqueo. Para obtener más información sobre cómo establecer el socket sin bloqueo en modo de bloqueo, consulte las funciones ioctlsocket y WSAIoctl .
El parámetro lEvent se construye mediante el operador OR bit a bit con cualquier valor enumerado en la tabla siguiente.
Valor | Significado |
---|---|
FD_READ | Establézcalo para recibir notificaciones de preparación para la lectura. |
FD_WRITE | Quiere recibir notificaciones de preparación para escribir. |
FD_OOB | Quiere recibir una notificación de la llegada de datos de OOB. |
FD_ACCEPT | Quiere recibir una notificación de las conexiones entrantes. |
FD_CONNECT | Quiere recibir una notificación de la conexión completada o de la operación de combinación multipunto. |
FD_CLOSE | Quiere recibir una notificación de cierre de socket. |
FD_QOS | Quiere recibir la notificación de los cambios de calidad de servicio (QoS) de sockets. |
FD_GROUP_QOS | Quiere recibir notificaciones de cambios de calidad de servicio (QoS) del grupo de sockets (reservados para uso futuro con grupos de sockets). Reservado. |
FD_ROUTING_INTERFACE_CHANGE | Quiere recibir la notificación de los cambios de la interfaz de enrutamiento para los destinos especificados. |
FD_ADDRESS_LIST_CHANGE | Quiere recibir la notificación de los cambios de la lista de direcciones locales para la familia de protocolos de socket. |
La emisión de un WSAAsyncSelect para un socket cancela cualquier WSAAsyncSelect o WSAEventSelect anterior para el mismo socket. Por ejemplo, para recibir notificaciones de lectura y escritura, la aplicación debe llamar a WSAAsyncSelect con FD_READ y FD_WRITE, como se indica a continuación:
rc = WSAAsyncSelect(s, hWnd, wMsg, FD_READ|FD_WRITE);
No es posible especificar mensajes diferentes para eventos diferentes. El código siguiente no funcionará; la segunda llamada cancelará los efectos del primero y solo se notificarán FD_WRITE eventos con el mensaje wMsg2:
rc = WSAAsyncSelect(s, hWnd, wMsg1, FD_READ);
rc = WSAAsyncSelect(s, hWnd, wMsg2, FD_WRITE);
Para cancelar todas las notificaciones que indican que Windows Sockets no debe enviar más mensajes relacionados con los eventos de red en el socket, lEvent se establece en cero.
rc = WSAAsyncSelect(s, hWnd, 0, 0);
Aunque WSAAsyncSelect deshabilita inmediatamente la publicación de mensajes de eventos para el socket en esta instancia, es posible que los mensajes puedan estar esperando en la cola de mensajes de la aplicación. Por lo tanto, la aplicación debe estar preparada para recibir mensajes de eventos de red incluso después de la cancelación. Al cerrar un socket con closesocket también se cancela el envío de mensajes WSAAsyncSelect , pero sigue siendo aplicable la misma advertencia sobre los mensajes de la cola.
El socket creado por la función accept tiene las mismas propiedades que el socket de escucha utilizado para aceptarlo. Por lo tanto, los eventos WSAAsyncSelect establecidos para el socket de escucha también se aplican al socket aceptado. Por ejemplo, si un socket de escucha tiene eventos WSAAsyncSelectFD_ACCEPT, FD_READ y FD_WRITE, cualquier socket aceptado en ese socket de escucha también tendrá FD_ACCEPT, FD_READ y eventos FD_WRITE con el mismo valor de wMsg usado para los mensajes. Si se desea otro wMsg o eventos, la aplicación debe llamar a WSAAsyncSelect, pasando el socket aceptado y los nuevos datos deseados.
Cuando se produce uno de los eventos de red designados en los sockets especificados, la ventana de aplicación hWnd recibe el mensaje wMsg. El parámetro wParam identifica el socket en el que se ha producido un evento de red. La palabra baja de lParam especifica el evento de red que se ha producido. La palabra alta de lParam contiene cualquier código de error. El código de error es cualquier error tal y como se define en Winsock2.h.
#include <windows.h>
#define WSAGETSELECTEVENT(lParam) LOWORD(lParam)
#define WSAGETSELECTERROR(lParam) HIWORD(lParam)
El uso de estas macros maximizará la portabilidad del código fuente de la aplicación.
Los posibles códigos de evento de red que se pueden devolver se enumeran en la tabla siguiente.
Valor | Significado |
---|---|
FD_READ | Sockets listos para leer. |
FD_WRITE | Socket está listo para escribir. |
FD_OOB | Datos de OOB listos para leer en sockets |
FD_ACCEPT | Sockets listos para aceptar una nueva conexión entrante. |
FD_CONNECT | Operación de conexión o combinación multipunto iniciada en los sockets completados . |
FD_CLOSE | Se ha cerrado la conexión identificada por sockets . |
FD_QOS | La calidad del servicio asociado a sockets ha cambiado. |
FD_GROUP_QOS | Reservado. La calidad del servicio asociado al grupo de sockets al que pertenece ha cambiado (reservado para uso futuro con grupos de sockets). |
FD_ROUTING_INTERFACE_CHANGE | La interfaz local que se debe usar para enviar al destino especificado ha cambiado. |
FD_ADDRESS_LIST_CHANGE | La lista de direcciones de la familia de protocolos de socket a la que el cliente de la aplicación puede enlazar ha cambiado. |
Aunque se puede llamar a WSAAsyncSelect con interés en varios eventos, la ventana de la aplicación recibirá un único mensaje para cada evento de red.
Como en el caso de la función select , WSAAsyncSelect se usará con frecuencia para determinar cuándo se puede emitir una operación de transferencia de datos (send o recv) con la expectativa de éxito inmediato. Sin embargo, una aplicación sólida debe estar preparada para la posibilidad de que pueda recibir un mensaje y emitir una llamada a Windows Sockets 2 que devuelva WSAEWOULDBLOCK inmediatamente. Por ejemplo, es posible la siguiente secuencia de eventos:
- Los datos llegan a los sockets; Windows Sockets 2 publica WSAAsyncSelect message
- La aplicación procesa algún otro mensaje
- Durante el procesamiento, la aplicación emite y
ioctlsocket(s, FIONREAD...)
observa que hay datos listos para leerse. - La aplicación emite para
recv(s,...)
leer los datos - Application bucles para procesar el siguiente mensaje, llegando finalmente al mensaje WSAAsyncSelect que indica que los datos están listos para leer
-
recv(s,...)
Problemas de la aplicación , que produce el error WSAEWOULDBLOCK.
El WS2_32.DLL no inundará continuamente una aplicación con mensajes para un evento de red determinado. Después de haber publicado correctamente una notificación de un evento determinado en una ventana de aplicación, no se publicarán más mensajes para ese evento de red en la ventana de la aplicación hasta que la aplicación realice la llamada de función que vuelva a habilitar implícitamente la notificación de ese evento de red.
Evento | Volver a habilitar la función |
---|---|
FD_READ | recv, recvfrom, WSARecv o WSARecvFrom. |
FD_WRITE | send, sendto, WSASend o WSASendTo. |
FD_OOB | recv, recvfrom, WSARecv o WSARecvFrom. |
FD_ACCEPT | accept o WSAAccept a menos que se WSATRY_AGAIN el código de error que indica que la función condition devolvió CF_DEFER. |
FD_CONNECT | Ninguno. |
FD_CLOSE | Ninguno. |
FD_QOS | WSAIoctl con SIO_GET_QOS de comandos. |
FD_GROUP_QOS | Reservado. WSAIoctl con SIO_GET_GROUP_QOS de comandos (reservado para uso futuro con grupos de sockets). |
FD_ROUTING_INTERFACE_CHANGE | WSAIoctl con SIO_ROUTING_INTERFACE_CHANGE de comandos. |
FD_ADDRESS_LIST_CHANGE | WSAIoctl con SIO_ADDRESS_LIST_CHANGE de comandos. |
Cualquier llamada a la rutina de volver a habilitar, incluso una que produce un error, da como resultado volver a habilitar la publicación de mensajes para el evento pertinente.
Para los eventos de FD_READ, FD_OOB y FD_ACCEPT , la publicación de mensajes se desencadena a nivel. Esto significa que si se llama a la rutina de volver a habilitar y la condición pertinente se sigue cumpliendo después de la llamada, se publica un mensaje WSAAsyncSelect en la aplicación. Esto permite que una aplicación esté controlada por eventos y no se preocupe por la cantidad de datos que llegan en cualquier momento. Considere la siguiente secuencia:
- La pila de transporte de red recibe 100 bytes de datos en sockets s y hace que Windows Sockets 2 publique un mensaje de FD_READ .
- La aplicación emite recv( s, buffptr, 50, 0) para leer 50 bytes.
- Otro mensaje de FD_READ se publica porque todavía hay datos que se van a leer.
Los eventos FD_QOS y FD_GROUP_QOS se consideran desencadenados en el perímetro. Un mensaje se publicará exactamente una vez cuando se produzca un cambio de calidad de servicio. Los mensajes adicionales no estarán disponibles hasta que el proveedor detecte un cambio adicional en la calidad del servicio o la aplicación renegocia la calidad del servicio para el socket.
El mensaje de FD_ROUTING_INTERFACE_CHANGE se publica cuando se debe usar la interfaz local que se debe usar para llegar al destino especificado en WSAIoctl con SIO_ROUTING_INTERFACE_CHANGE cambios después de que se haya emitido dicho IOCTL.
El mensaje FD_ADDRESS_LIST_CHANGE se publica cuando se ha emitido la lista de direcciones a las que la aplicación puede enlazar los cambios después de que se haya emitido WSAIoctl con SIO_ADDRESS_LIST_CHANGE.
Si se ha producido algún evento cuando la aplicación llama a WSAAsyncSelect o cuando se llama a la función de reen habilitación, se publica un mensaje según corresponda. Considere, por ejemplo, la secuencia siguiente:
- Una aplicación llama a la escucha.
- Se recibe una solicitud de conexión, pero aún no se acepta.
- La aplicación llama a WSAAsyncSelect especificando que requiere recibir mensajes FD_ACCEPT para el socket. Debido a la persistencia de eventos, Windows Sockets 2 publica inmediatamente un mensaje FD_ACCEPT .
El evento FD_WRITE se controla de forma ligeramente diferente. Se publica un mensaje de FD_WRITE cuando un socket se conecta por primera vez con connect o WSAConnect (después de FD_CONNECT, si también está registrado) o se acepta con accept o WSAAccept, y después de que se produzca un error en una operación de envío con WSAEWOULDBLOCK y el espacio de búfer esté disponible. Por lo tanto, una aplicación puede suponer que los envíos son posibles a partir del primer mensaje de FD_WRITE y duradero hasta que un envío devuelve WSAEWOULDBLOCK. Después de este error, se notificará a la aplicación que los envíos son posibles de nuevo con un mensaje de FD_WRITE .
El evento FD_OOB solo se usa cuando un socket está configurado para recibir datos OOB por separado. Si el socket está configurado para recibir datos de OOB insertados, los datos de OOB (acelerados) se tratan como datos normales y la aplicación debe registrar un interés en, y recibirá, FD_READ eventos, no FD_OOB eventos. Una aplicación puede establecer o inspeccionar la forma en que se van a controlar los datos de OOB mediante setsockopt o getsockopt para la opción SO_OOBINLINE.
El código de error de un mensaje de FD_CLOSE indica si el cierre del socket era correcto o abortivo. Si el código de error es cero, el cierre fue correcto; Si el código de error es WSAECONNRESET, se restableció el circuito virtual del socket. Esto solo se aplica a sockets orientados a la conexión, como SOCK_STREAM.
El FD_CLOSE mensaje se publica cuando se recibe una indicación de cierre para el circuito virtual correspondiente al socket. En términos TCP, esto significa que el FD_CLOSE se publica cuando la conexión entra en los estados TIME WAIT o CLOSE WAIT. Esto resulta del extremo remoto que realiza un apagado en el lado de envío o en un closesocket. FD_CLOSE solo se deben publicar después de que se lean todos los datos de un socket, pero una aplicación debe comprobar los datos restantes al recibir FD_CLOSE para evitar la posibilidad de perder datos.
Tenga en cuenta que la aplicación solo recibirá un mensaje de FD_CLOSE para indicar el cierre de un circuito virtual y solo cuando se hayan leído todos los datos recibidos si se trata de un cierre correcto. No recibirá un mensaje de FD_READ para indicar esta condición.
El mensaje FD_QOS o FD_GROUP_QOS se publica cuando cualquier parámetro de la especificación de flujo asociada a sockets o al grupo de sockets al que pertenece ha cambiado, respectivamente. Las aplicaciones deben usar WSAIoctl con el comando SIO_GET_QOS o SIO_GET_GROUP_QOS para obtener la calidad actual del servicio para sockets o para que el grupo de sockets pertenezca, respectivamente.
Los eventos de FD_ROUTING_INTERFACE_CHANGE y FD_ADDRESS_LIST_CHANGE también se consideran desencadenados en el perímetro. Un mensaje se publicará exactamente una vez cuando se produzca un cambio después de que la aplicación haya solicitado la notificación emitiendo WSAIoctl con SIO_ROUTING_INTERFACE_CHANGE o SIO_ADDRESS_LIST_CHANGE correspondientemente. Los mensajes adicionales no estarán disponibles hasta que la aplicación vuelva a emitir el IOCTL y se detecte otro cambio porque se ha emitido el IOCTL.
Este es un resumen de eventos y condiciones para cada mensaje de notificación asincrónico.
-
FD_READ:
- Cuando se llama a WSAAsyncSelect , si hay datos disponibles actualmente para recibir.
- Cuando llegan los datos, si FD_READ aún no se ha publicado.
- Después de llamar a recv o recvfrom , con o sin MSG_PEEK), si los datos siguen estando disponibles para recibirse.
Nota Cuando se habilita setsockopt SO_OOBINLINE, los datos incluyen datos normales y datos OOB en las instancias indicadas anteriormente.
-
FD_WRITE:
- Cuando se llama a WSAAsyncSelect, si es posible enviar oenviar.
- Después de llamar a connect o accept , cuando se establece la conexión.
- Después de enviar o enviar para producir un error con WSAEWOULDBLOCK, es probable que el envío o el envío se realicen correctamente.
- Después de enlazar en un socket sin conexión. FD_WRITE puede ocurrir o no en este momento (dependiente de la implementación). En cualquier caso, un socket sin conexión siempre se puede escribir inmediatamente después de una operación de enlace .
-
FD_OOB: solo es válido cuando setockopt SO_OOBINLINE está deshabilitado (valor predeterminado).
- Cuando se llama a WSAAsyncSelect , si hay datos OOB disponibles actualmente para recibirlos con la marca MSG_OOB.
- Cuando llegan los datos de OOB, si FD_OOB aún no se han publicado.
- Después de llamar a recv o recvfrom con o sin MSG_OOB marca, si los datos de OOB siguen estando disponibles para recibirse.
-
FD_ACCEPT:
- Cuando se llama a WSAAsyncSelect , si actualmente hay una solicitud de conexión disponible para aceptar.
- Cuando llega una solicitud de conexión, si FD_ACCEPT aún no se ha publicado.
- Después de llamar a accept , si hay otra solicitud de conexión disponible para aceptar.
-
FD_CONNECT:
- Cuando se llama a WSAAsyncSelect , si actualmente hay una conexión establecida.
- Después de llamar a connect , cuando se establece la conexión, incluso cuando la conexión se realiza correctamente inmediatamente, como es habitual con un socket de datagrama.
- Después de llamar a WSAJoinLeaf, cuando se complete la operación de combinación.
- Después de conectarse, se llamó a WSAConnect o WSAJoinLeaf con un socket orientado a conexiones sin bloqueo. La operación inicial devolvió un error específico de WSAEWOULDBLOCK, pero la operación de red siguió adelante. Si la operación se realiza correctamente o no, cuando se ha determinado el resultado, FD_CONNECT se produce. El cliente debe comprobar el código de error para determinar si el resultado se realizó correctamente o no.
-
FD_CLOSE: solo válido en sockets orientados a la conexión (por ejemplo, SOCK_STREAM)
- Cuando se llama a WSAAsyncSelect , si se ha cerrado la conexión de socket.
- Después del cierre correcto iniciado por el sistema remoto, cuando no haya datos disponibles actualmente para recibirlos (tenga en cuenta que, si se han recibido datos y está esperando leerse cuando el sistema remoto inicia un cierre correcto, la FD_CLOSE no se entrega hasta que se hayan leído todos los datos pendientes).
- Una vez que el sistema local inicia un cierre correcto con el apagado y el sistema remoto ha respondido con la notificación "Fin de los datos" (por ejemplo, TCP FIN), cuando no hay datos disponibles actualmente para recibir.
- Cuando el sistema remoto finaliza la conexión (por ejemplo, TCP RST enviado) y lParam contendrá el valor de error WSAECONNRESET .
NotaFD_CLOSE no se publica después de llamar a closesocket .
-
FD_QOS:
- Cuando se llama a WSAAsyncSelect , si se ha cambiado la calidad del servicio asociado al socket.
- Después de WSAIoctl con SIO_GET_QOS llamado, cuando se cambia la calidad del servicio.
- FD_GROUP_QOS: Reservado.
-
FD_ROUTING_INTERFACE_CHANGE:
- Después de WSAIoctl con SIO_ROUTING_INTERFACE_CHANGE llamado, cuando la interfaz local que se debe usar para llegar al destino especificado en el IOCTL cambia.
-
FD_ADDRESS_LIST_CHANGE:
- Después de WSAIoctl con SIO_ADDRESS_LIST_CHANGE llamado, cuando se llama a la lista de direcciones locales a las que la aplicación puede enlazar los cambios.
Requisitos
Requisito | Value |
---|---|
Cliente mínimo compatible | Windows 2000 Professional [solo aplicaciones de escritorio] |
Servidor mínimo compatible | Windows 2000 Server [solo aplicaciones de escritorio] |
Plataforma de destino | Windows |
Encabezado | winsock.h (incluya Winsock2.h) |
Library | Ws2_32.lib |
Archivo DLL | Ws2_32.dll |