Compartilhar via


Função WSAAsyncSelect (winsock2.h)

[A função WSAAsyncSelect está disponível para uso nos sistemas operacionais especificados na seção Requisitos. Ele poderá ser alterado ou ficar indisponível em versões subsequentes. Em vez de usar E/S no estilo Select, use E /S sobreposta e Objetos de Evento com WinSock2.]

A função WSAAsyncSelect solicita a notificação baseada em mensagens do Windows de eventos de rede para um soquete.

Sintaxe

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

Parâmetros

[in] s

Um descritor que identifica o soquete para o qual a notificação de evento é necessária.

[in] hWnd

Um identificador que identifica a janela que receberá uma mensagem quando ocorrer um evento de rede.

[in] wMsg

Uma mensagem a ser recebida quando ocorrer um evento de rede.

[in] lEvent

Uma máscara de bits, a qual especifica uma combinação de eventos de rede em que o aplicativo está interessado.

Retornar valor

Se a função WSAAsyncSelect for bem-sucedida, o valor retornado será zero, desde que a declaração de interesse do aplicativo no conjunto de eventos de rede tenha sido bem-sucedida. Caso contrário, o valor SOCKET_ERROR será retornado e um número de erro específico poderá ser recuperado chamando WSAGetLastError.

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.
WSAEINVAL
Um dos parâmetros especificados era inválido, como o identificador de janela que não se refere a uma janela existente ou o soquete especificado está em um estado inválido.
WSAEINPROGRESS
Uma chamada de bloqueio do Windows Sockets 1.1 está em andamento ou o provedor de serviços ainda está processando uma função de retorno de chamada.
WSAENOTSOCK
O descritor não é um soquete.
 

Códigos de erro adicionais podem ser definidos quando uma janela do aplicativo recebe uma mensagem. Esse código de erro é extraído do lParam na mensagem de resposta usando a macro WSAGETSELECTERROR . Os códigos de erro possíveis para cada evento de rede são listados na tabela a seguir.

Evento: FD_CONNECT

Código do erro Significado
WSAEAFNOSUPPORT Os endereços na família especificada não podem ser usados com este soquete.
WSAECONNREFUSED A tentativa de conexão foi rejeitada.
WSAENETUNREACH A rede não pode ser alcançada através deste host neste momento.
WSAEFAULT O parâmetro namelen é inválido.
WSAEINVAL O soquete já está associado a um endereço.
WSAEISCONN O soquete já está conectado.
WSAEMFILE Nenhum outro descritor de arquivo disponível.
WSAENOBUFS Nenhum espaço de buffer disponível. O soquete não pode ser conectado.
WSAENOTCONN O soquete não está conectado.
WSAETIMEDOUT Tente se conectar com o tempo limite sem estabelecer uma conexão.
 

Evento: FD_CLOSE

Código do erro Significado
WSAENETDOWN O subsistema de rede falhou.
WSAECONNRESET A conexão foi redefinida pelo lado remoto.
WSAECONNABORTED A conexão foi encerrada devido a um tempo limite ou outra falha.
 
Código do erro Significado
WSAENETDOWN O subsistema de rede falhou.
 

Evento: FD_ROUTING_INTERFACE_CHANGE

Código do erro Significado
WSAENETUNREACH O destino especificado não é mais acessível.
WSAENETDOWN O subsistema de rede falhou.

Comentários

A função WSAAsyncSelect é usada para solicitar que WS2_32.DLL envie uma mensagem para a janela hWnd quando detectar qualquer evento de rede especificado pelo parâmetro lEvent . A mensagem que deve ser enviada é especificada pelo parâmetro wMsg . O soquete para o qual a notificação é necessária é identificado pelo parâmetro s .

A função WSAAsyncSelect define automaticamente o soquete s para o modo sem bloqueio, independentemente do valor de lEvent. Para definir o soquete de volta para o modo de bloqueio, primeiro é necessário limpar o registro de evento associado a soquetes por meio de uma chamada para WSAAsyncSelect com lEvent definido como zero. Em seguida, você pode chamar ioctlsocket ou WSAIoctl para definir o soquete de volta para o modo de bloqueio. Para obter mais informações sobre como definir o soquete sem bloqueio de volta para o modo de bloqueio, consulte as funções ioctlsocket e WSAIoctl .

O parâmetro lEvent é construído usando o operador OR bit a bit com qualquer valor listado na tabela a seguir.

Valor Significado
FD_READ Defina para receber uma notificação de preparação para leitura.
FD_WRITE Deseja receber uma notificação de preparação para gravação.
FD_OOB Deseja receber uma notificação da chegada de dados OOB.
FD_ACCEPT Deseja receber uma notificação de conexões de entrada.
FD_CONNECT Deseja receber uma notificação de conexão concluída ou operação de junção de vários pontos.
FD_CLOSE Deseja receber uma notificação de fechamento do soquete.
FD_QOS Deseja receber a notificação de alterações de QoS (Qualidade de Serviço) do soquete.
FD_GROUP_QOS Deseja receber notificação de alterações de QoS (Qualidade de Serviço) do grupo de soquetes (reservado para uso futuro com grupos de soquetes). Reservado.
FD_ROUTING_INTERFACE_CHANGE Deseja receber uma notificação de alterações de interface de roteamento para os destinos especificados.
FD_ADDRESS_LIST_CHANGE Deseja receber a notificação de alterações na lista de endereços locais para a família de protocolos de soquete.
 

Emitir um WSAAsyncSelect para um soquete cancela qualquer WSAAsyncSelect ou WSAEventSelect anterior para o mesmo soquete. Por exemplo, para receber notificação para leitura e gravação, o aplicativo deve chamar WSAAsyncSelect com FD_READ e FD_WRITE, da seguinte maneira:

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

Não é possível especificar mensagens diferentes para eventos diferentes. O código a seguir não funcionará; a segunda chamada cancelará os efeitos do primeiro e somente FD_WRITE eventos serão relatados com a mensagem wMsg2:

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

Para cancelar toda a notificação indicando que os Soquetes do Windows não devem enviar mais mensagens relacionadas a eventos de rede no soquete, o lEvent está definido como zero.

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

Embora o WSAAsyncSelect desabilite imediatamente a postagem de mensagem de evento para o soquete nesta instância, é possível que as mensagens possam estar aguardando na fila de mensagens do aplicativo. Portanto, o aplicativo deve estar preparado para receber mensagens de evento de rede mesmo após o cancelamento. Fechar um soquete com closesocket também cancela o envio de mensagens WSAAsyncSelect , mas a mesma ressalva sobre mensagens na fila ainda se aplica.

O soquete criado pela função accept tem as mesmas propriedades que o soquete de escuta usado para aceitá-lo. Consequentemente, os eventos WSAAsyncSelect definidos para o soquete de escuta também se aplicam ao soquete aceito. Por exemplo, se um soquete de escuta tiver eventos WSAAsyncSelectFD_ACCEPT, FD_READ e FD_WRITE, qualquer soquete aceito nesse soquete de escuta também terá eventos FD_ACCEPT, FD_READ e FD_WRITE com o mesmo valor wMsg usado para mensagens. Se um wMsg ou eventos diferentes forem desejados, o aplicativo deverá chamar WSAAsyncSelect, passando o soquete aceito e os novos dados desejados.

Quando um dos eventos de rede nomeados ocorre nos soquetes especificados , a janela do aplicativo hWnd recebe a mensagem wMsg. O parâmetro wParam identifica o soquete no qual ocorreu um evento de rede. A palavra baixa de lParam especifica o evento de rede que ocorreu. A palavra alta de lParam contém qualquer código de erro. O código de erro é qualquer erro conforme definido em Winsock2.h.

Nota Após o recebimento de uma mensagem de notificação de evento, a função WSAGetLastError não pode ser usada para marcar o valor de erro porque o valor de erro retornado pode ser diferente do valor na palavra alta lParam.
 
Os códigos de erro e evento podem ser extraídos do lParam usando as macros WSAGETSELECTERROR e WSAGETSELECTEVENT, definidas em Winsock2.h como:
#include <windows.h>

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

O uso dessas macros maximizará a portabilidade do código-fonte para o aplicativo.

Os possíveis códigos de evento de rede que podem ser retornados são listados na tabela a seguir.

Valor Significado
FD_READ Soquete pronto para leitura.
FD_WRITE Soquete pronto para gravação.
FD_OOB Dados OOB prontos para leitura em soquetes
FD_ACCEPT O soquete está pronto para aceitar uma nova conexão de entrada.
FD_CONNECT Conexão ou operação de junção de vários pontos iniciada no soquete concluído .
FD_CLOSE A conexão identificada pelo soquete foi fechada.
FD_QOS A qualidade de serviço associada ao soquete foi alterada.
FD_GROUP_QOS Reservado. A qualidade de serviço associada ao grupo de soquetes ao qual s pertence foi alterada (reservada para uso futuro com grupos de soquetes).
FD_ROUTING_INTERFACE_CHANGE A interface local que deve ser usada para enviar para o destino especificado foi alterada.
FD_ADDRESS_LIST_CHANGE A lista de endereços da família de protocolos de soquete à qual o cliente do aplicativo pode associar foi alterada.
 

Embora o WSAAsyncSelect possa ser chamado com interesse em vários eventos, a janela do aplicativo receberá uma única mensagem para cada evento de rede.

Como no caso da função select , WSAAsyncSelect será frequentemente usado para determinar quando uma operação de transferência de dados (enviar ou rev) pode ser emitida com a expectativa de sucesso imediato. No entanto, um aplicativo robusto deve estar preparado para a possibilidade de receber uma mensagem e emitir uma chamada do Windows Sockets 2 que retorna WSAEWOULDBLOCK imediatamente. Por exemplo, a seguinte sequência de eventos é possível:

  1. Os dados chegam em soquetes ; Mensagem WSAAsyncSelect de postagens do Windows Sockets 2
  2. O aplicativo processa outra mensagem
  3. Durante o processamento, o aplicativo emite um ioctlsocket(s, FIONREAD...) e percebe que há dados prontos para leitura
  4. O aplicativo emite um recv(s,...) para ler os dados
  5. O aplicativo faz loops para processar a próxima mensagem, chegando eventualmente à mensagem WSAAsyncSelect indicando que os dados estão prontos para leitura
  6. Problemas do recv(s,...)aplicativo , que falha com o erro WSAEWOULDBLOCK.
Outras sequências também são possíveis.

O WS2_32.DLL não inundará continuamente um aplicativo com mensagens para um evento de rede específico. Depois de postar com êxito a notificação de um evento específico em uma janela do aplicativo, nenhuma mensagem adicional para esse evento de rede será postada na janela do aplicativo até que o aplicativo faça a chamada de função que reativa implicitamente a notificação desse evento de rede.

Evento Função reenabling
FD_READ recv, recvfrom, WSARecv ou WSARecvFrom.
FD_WRITE send, sendto, WSASend ou WSASendTo.
FD_OOB recv, recvfrom, WSARecv ou WSARecvFrom.
FD_ACCEPT accept ou WSAAccept , a menos que o código de erro seja WSATRY_AGAIN indicando que a função de condição retornou CF_DEFER.
FD_CONNECT Nenhum.
FD_CLOSE Nenhum.
FD_QOS WSAIoctl com SIO_GET_QOS de comando.
FD_GROUP_QOS Reservado. WSAIoctl com SIO_GET_GROUP_QOS de comando (reservado para uso futuro com grupos de soquetes).
FD_ROUTING_INTERFACE_CHANGE WSAIoctl com SIO_ROUTING_INTERFACE_CHANGE de comando.
FD_ADDRESS_LIST_CHANGE WSAIoctl com SIO_ADDRESS_LIST_CHANGE de comando.
 

Qualquer chamada para a rotina de reenabling, mesmo que falhe, resulta em uma nova busca de postagem de mensagem para o evento relevante.

Para eventos FD_READ, FD_OOB e FD_ACCEPT , a postagem de mensagens é disparada em nível. Isso significa que, se a rotina de repetição for chamada e a condição relevante ainda for atendida após a chamada, uma mensagem WSAAsyncSelect será postada no aplicativo. Isso permite que um aplicativo seja controlado por eventos e não se preocupou com a quantidade de dados que chegam de uma só vez. Considere a sequência a seguir:

  1. A pilha de transporte de rede recebe 100 bytes de dados em soquetes e faz com que o Windows Sockets 2 poste uma mensagem FD_READ .
  2. O aplicativo emite recv( s, buffptr, 50, 0) para ler 50 bytes.
  3. Outra mensagem FD_READ é postada porque ainda há dados a serem lidos.
Com essas semânticas, um aplicativo não precisa ler todos os dados disponíveis em resposta a uma mensagem FD_READ — um único recv em resposta a cada mensagem FD_READ é apropriado. Se um aplicativo emitir várias chamadas recv em resposta a uma única FD_READ, ele poderá receber várias mensagens FD_READ . Esse aplicativo pode exigir a desabilitação FD_READ mensagens antes de iniciar as chamadas recv chamando WSAAsyncSelect com o evento FD_READ não definido.

Os eventos FD_QOS e FD_GROUP_QOS são considerados gatilhos de borda. Uma mensagem será postada exatamente uma vez quando ocorrer uma alteração de qualidade de serviço. Outras mensagens não serão enviadas até que o provedor detecte uma nova alteração na qualidade do serviço ou o aplicativo renegocie a qualidade do serviço para o soquete.

A mensagem FD_ROUTING_INTERFACE_CHANGE é postada quando a interface local que deve ser usada para alcançar o destino especificado em WSAIoctl com SIO_ROUTING_INTERFACE_CHANGE é alterada após a emissão desse IOCTL.

A mensagem FD_ADDRESS_LIST_CHANGE é postada quando a lista de endereços aos quais o aplicativo pode associar alterações após a emissão do WSAIoctl com SIO_ADDRESS_LIST_CHANGE.

Se algum evento tiver ocorrido quando o aplicativo chamar WSAAsyncSelect ou quando a função reenabling for chamada, uma mensagem será postada conforme apropriado. Por exemplo, considere a seguinte sequência:

  1. Um aplicativo chama listen.
  2. Uma solicitação de conexão é recebida, mas ainda não aceita.
  3. O aplicativo chama WSAAsyncSelect especificando que ele requer o recebimento FD_ACCEPT mensagens para o soquete. Devido à persistência de eventos, o Windows Sockets 2 posta uma mensagem FD_ACCEPT imediatamente.
O evento FD_WRITE é tratado de forma ligeiramente diferente. Uma mensagem FD_WRITE é postada quando um soquete é conectado pela primeira vez com connect ou WSAConnect (após FD_CONNECT, se também registrado) ou aceito com accept ou WSAAccept, e depois que uma operação de envio falha com WSAEWOULDBLOCK e o espaço de buffer fica disponível. Portanto, um aplicativo pode assumir que os envios são possíveis a partir da primeira mensagem FD_WRITE e durando até que um envio retorne WSAEWOULDBLOCK. Após essa falha, o aplicativo será notificado de que os envios são novamente possíveis com uma mensagem FD_WRITE .

O evento FD_OOB é usado somente quando um soquete é configurado para receber dados OOB separadamente. Se o soquete estiver configurado para receber dados OOB embutidos, os dados OOB (agilizados) serão tratados como dados normais e o aplicativo deverá registrar um interesse em, e receberá, FD_READ eventos, não FD_OOB eventos. Um aplicativo pode definir ou inspecionar a maneira como os dados OOB devem ser tratados usando setsockopt ou getsockopt para a opção SO_OOBINLINE.

O código de erro em uma mensagem FD_CLOSE indica se o fechamento do soquete foi normal ou anulativo. Se o código de erro for zero, o fechamento foi normal; se o código de erro for WSAECONNRESET, o circuito virtual do soquete será redefinido. Isso só se aplica a soquetes orientados à conexão, como SOCK_STREAM.

A mensagem FD_CLOSE é postada quando uma indicação próxima é recebida para o circuito virtual correspondente ao soquete. Em termos TCP, isso significa que o FD_CLOSE é postado quando a conexão entra nos estados TIME WAIT ou CLOSE WAIT. Isso resulta da extremidade remota executando um desligamento no lado de envio ou um closesocket. FD_CLOSE só deve ser postado depois que todos os dados são lidos de um soquete, mas um aplicativo deve marcar para os dados restantes após o recebimento de FD_CLOSE para evitar qualquer possibilidade de perda de dados.

Lembre-se de que o aplicativo receberá apenas uma mensagem FD_CLOSE para indicar o fechamento de um circuito virtual e somente quando todos os dados recebidos forem lidos se este for um fechamento normal. Ele não receberá uma mensagem FD_READ para indicar essa condição.

A mensagem FD_QOS ou FD_GROUP_QOS é postada quando qualquer parâmetro na especificação de fluxo associado ao soquete ou ao grupo de soquetes ao qual pertence foi alterado, respectivamente. Os aplicativos devem usar WSAIoctl com SIO_GET_QOS de comando ou SIO_GET_GROUP_QOS para obter a qualidade atual do serviço para soquetes ou para o grupo de soquetes ao qual pertence, respectivamente.

Os eventos FD_ROUTING_INTERFACE_CHANGE e FD_ADDRESS_LIST_CHANGE também são considerados gatilhos de borda. Uma mensagem será postada exatamente uma vez quando ocorrer uma alteração depois que o aplicativo solicitar a notificação emitindo WSAIoctl com SIO_ROUTING_INTERFACE_CHANGE ou SIO_ADDRESS_LIST_CHANGE correspondentemente. Outras mensagens não serão enviadas até que o aplicativo reissua o IOCTL e outra alteração seja detectada porque o IOCTL foi emitido.

Aqui está um resumo de eventos e condições para cada mensagem de notificação assíncrona.

  • FD_READ:
    1. Quando WSAAsyncSelect for chamado, se houver dados disponíveis para receber no momento.
    2. Quando os dados chegam, se FD_READ ainda não estiverem postados.
    3. Depois que recv ou recvfrom for chamado, com ou sem MSG_PEEK), se os dados ainda estiverem disponíveis para receber.
      Nota Quando setsockopt SO_OOBINLINE está habilitado, os dados incluem dados normais e OOB nas instâncias indicadas acima.
       
  • FD_WRITE:
    1. Quando WSAAsyncSelect chamado, se um send ou sendto for possível.
    2. Depois de conectar ou aceitar chamado, quando a conexão for estabelecida.
    3. Depois de enviar ou enviar para falhar com WSAEWOULDBLOCK, quando send ou sendto provavelmente terá êxito.
    4. Depois de associar em um soquete sem conexão. FD_WRITE pode ou não ocorrer neste momento (dependente da implementação). De qualquer forma, um soquete sem conexão é sempre gravável imediatamente após uma operação de associação .
  • FD_OOB: válido somente quando setsockopt SO_OOBINLINE estiver desabilitado (padrão).
    1. Quando wsaAsyncSelect chamado, se houver dados OOB atualmente disponíveis para receber com o sinalizador MSG_OOB.
    2. Quando os dados OOB chegam, se ainda não FD_OOB postados.
    3. Depois de rev ou recvfrom chamado com ou sem MSG_OOB sinalizador, se os dados OOB ainda estiverem disponíveis para receber.
  • FD_ACCEPT:
    1. Quando wsaAsyncSelect chamado, se houver atualmente uma solicitação de conexão disponível para aceitar.
    2. Quando uma solicitação de conexão chega, se ainda não FD_ACCEPT postado.
    3. Depois de aceitar chamado, se houver outra solicitação de conexão disponível para aceitar.
  • FD_CONNECT:
    1. Quando WSAAsyncSelect chamado, se houver atualmente uma conexão estabelecida.
    2. Depois de conectar chamado, quando a conexão é estabelecida, mesmo quando a conexão é bem-sucedida imediatamente, como é típico com um soquete de datagrama.
    3. Depois de chamar WSAJoinLeaf, quando a operação de junção for concluída.
    4. Após a conexão, WSAConnect ou WSAJoinLeaf foi chamado com um soquete orientado a conexão sem bloqueio. A operação inicial retornada com um erro específico de WSAEWOULDBLOCK, mas a operação de rede foi adiante. Se a operação eventualmente for bem-sucedida ou não, quando o resultado tiver sido determinado, FD_CONNECT ocorrerá. O cliente deve marcar o código de erro para determinar se o resultado foi bem-sucedido ou falhou.
  • FD_CLOSE: válido somente em soquetes orientados à conexão (por exemplo, SOCK_STREAM)
    1. Quando WSAAsyncSelect chamado, se a conexão de soquete tiver sido fechada.
    2. Após o fechamento normal do sistema remoto, quando nenhum dado disponível para receber no momento (lembre-se de que, se os dados tiverem sido recebidos e estiverem aguardando para serem lidos quando o sistema remoto iniciar um fechamento normal, o FD_CLOSE não será entregue até que todos os dados pendentes sejam lidos).
    3. Depois que o sistema local iniciar o fechamento normal com o desligamento e o sistema remoto tiver respondido com a notificação "Fim dos Dados" (por exemplo, TCP FIN), quando nenhum dado disponível para receber no momento.
    4. Quando o sistema remoto encerra a conexão (por exemplo, TCP RST enviado), e lParam conterá o valor de erro WSAECONNRESET .
      ObservaçãoFD_CLOSE não é postado depois que closesocket é chamado.
       
  • FD_QOS:
    1. Quando WSAAsyncSelect chamado, se a qualidade do serviço associado ao soquete tiver sido alterada.
    2. Após o WSAIoctl com SIO_GET_QOS chamado, quando a qualidade do serviço é alterada.
  • FD_GROUP_QOS: Reservado.
  • FD_ROUTING_INTERFACE_CHANGE:
    • Depois que o WSAIoctl com SIO_ROUTING_INTERFACE_CHANGE chamado, quando a interface local que deve ser usada para alcançar o destino especificado no IOCTL é alterada.
  • FD_ADDRESS_LIST_CHANGE:
    • Após o WSAIoctl com SIO_ADDRESS_LIST_CHANGE chamado, quando a lista de endereços locais aos quais o aplicativo pode associar alterações.

Requisitos

Requisito Valor
Cliente mínimo com suporte Windows 2000 Professional [somente aplicativos da área de trabalho]
Servidor mínimo com suporte Windows 2000 Server [somente aplicativos da área de trabalho]
Plataforma de Destino Windows
Cabeçalho winsock2.h (inclua Winsock2.h)
Biblioteca Ws2_32.lib
DLL Ws2_32.dll

Confira também

Wsaeventselect

Funções Winsock

Referência de Winsock

select