Compartir a través de


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
WSANOTINITIALISED
Debe producirse una llamada WSAStartup correcta antes de usar esta función.
WSAENETDOWN
Error en el subsistema de red.
WSAEINVAL
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.
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.
WSAENOTSOCK
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.

Nota Tras recibir un mensaje de notificación de evento, no se puede usar la función WSAGetLastError para comprobar el valor de error porque el valor de error devuelto puede diferir del valor de la palabra alta de lParam.
 
Los códigos de error y evento se pueden extraer de lParam mediante las macros WSAGETSELECTERROR y WSAGETSELECTEVENT, definidas en Winsock2.h como:
#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:

  1. Los datos llegan a los sockets; Windows Sockets 2 publica WSAAsyncSelect message
  2. La aplicación procesa algún otro mensaje
  3. Durante el procesamiento, la aplicación emite y ioctlsocket(s, FIONREAD...) observa que hay datos listos para leerse.
  4. La aplicación emite para recv(s,...) leer los datos
  5. Application bucles para procesar el siguiente mensaje, llegando finalmente al mensaje WSAAsyncSelect que indica que los datos están listos para leer
  6. recv(s,...)Problemas de la aplicación , que produce el error WSAEWOULDBLOCK.
También se pueden realizar otras secuencias.

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:

  1. 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 .
  2. La aplicación emite recv( s, buffptr, 50, 0) para leer 50 bytes.
  3. Otro mensaje de FD_READ se publica porque todavía hay datos que se van a leer.
Con esta semántica, una aplicación no necesita leer todos los datos disponibles en respuesta a un mensaje de FD_READ , una única recv en respuesta a cada mensaje FD_READ es adecuada. Si una aplicación emite varias llamadas de recv en respuesta a un único FD_READ, puede recibir varios mensajes FD_READ . Esta aplicación puede requerir deshabilitar FD_READ mensajes antes de iniciar las llamadas de recv mediante una llamada a WSAAsyncSelect con el evento FD_READ no establecido.

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:

  1. Una aplicación llama a la escucha.
  2. Se recibe una solicitud de conexión, pero aún no se acepta.
  3. 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:
    1. Cuando se llama a WSAAsyncSelect , si hay datos disponibles actualmente para recibir.
    2. Cuando llegan los datos, si FD_READ aún no se ha publicado.
    3. 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:
    1. Cuando se llama a WSAAsyncSelect, si es posible enviar oenviar.
    2. Después de llamar a connect o accept , cuando se establece la conexión.
    3. 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.
    4. 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).
    1. Cuando se llama a WSAAsyncSelect , si hay datos OOB disponibles actualmente para recibirlos con la marca MSG_OOB.
    2. Cuando llegan los datos de OOB, si FD_OOB aún no se han publicado.
    3. 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:
    1. Cuando se llama a WSAAsyncSelect , si actualmente hay una solicitud de conexión disponible para aceptar.
    2. Cuando llega una solicitud de conexión, si FD_ACCEPT aún no se ha publicado.
    3. Después de llamar a accept , si hay otra solicitud de conexión disponible para aceptar.
  • FD_CONNECT:
    1. Cuando se llama a WSAAsyncSelect , si actualmente hay una conexión establecida.
    2. 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.
    3. Después de llamar a WSAJoinLeaf, cuando se complete la operación de combinación.
    4. 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)
    1. Cuando se llama a WSAAsyncSelect , si se ha cerrado la conexión de socket.
    2. 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).
    3. 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.
    4. 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:
    1. Cuando se llama a WSAAsyncSelect , si se ha cambiado la calidad del servicio asociado al socket.
    2. 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

Consulte también

WSAEventSelect

Funciones winsock

Referencia de Winsock

select