Compartilhar via


Função WSAEventSelect (winsock2.h)

A função WSAEventSelect especifica um objeto de evento a ser associado ao conjunto especificado de eventos de rede FD_XXX.

Sintaxe

int WSAAPI WSAEventSelect(
  [in] SOCKET   s,
  [in] WSAEVENT hEventObject,
  [in] long     lNetworkEvents
);

Parâmetros

[in] s

Um descritor que identifica o soquete.

[in] hEventObject

Um identificador que identifica o objeto de evento a ser associado ao conjunto especificado de FD_XXX eventos de rede.

[in] lNetworkEvents

Uma máscara de bits que especifica a combinação de FD_XXX eventos de rede nos quais o aplicativo tem interesse.

Retornar valor

O valor retornado será zero se a especificação do aplicativo dos eventos de rede e o objeto de evento associado tiver sido bem-sucedido. Caso contrário, o valor SOCKET_ERROR será retornado e um número de erro específico poderá ser recuperado chamando WSAGetLastError.

Como no caso das funções select e WSAAsyncSelect , WSAEventSelect 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 ser preparado para a possibilidade de que o objeto de evento esteja definido e emita uma chamada do Windows Sockets que retorna WSAEWOULDBLOCK imediatamente. Por exemplo, a seguinte sequência de operações é possível:

  • Os dados chegam no soquete s; O Windows Sockets define o objeto de evento WSAEventSelect .
  • O aplicativo faz algum outro processamento.
  • Durante o processamento, o aplicativo emite um ioctlsocket(s, FIONREAD...) e percebe que há dados prontos para serem lidos.
  • O aplicativo emite um recv(s,...) para ler os dados.
  • O aplicativo eventualmente aguarda o objeto de evento especificado em WSAEventSelect, que retorna imediatamente indicando que os dados estão prontos para leitura.
  • O aplicativo emite recv(s,...), que falha com o erro WSAEWOULDBLOCK.
Tendo registrado com êxito a ocorrência do evento de rede (definindo o bit correspondente no registro de evento de rede interno) e sinalizado o objeto de evento associado, nenhuma outra ação será tomada para esse evento de rede até que o aplicativo faça a chamada de função que implicitamente reabilita a configuração desse evento de rede e a sinalização do objeto de evento associado.
Evento de rede Reabilitando a função
FD_READ
A função recv, recvfrom, WSARecv, WSARecvEx ou WSARecvFrom .
FD_WRITE
A função send, sendto, WSASend ou WSASendTo .
FD_OOB
A função recv, recvfrom, WSARecv, WSARecvEx ou WSARecvFrom .
FD_ACCEPT
A função accept, AcceptEx ou WSAAccept , a menos que o código de erro retornado seja WSATRY_AGAIN indicando que a função de condição retornada CF_DEFER.
FD_CONNECT
Nenhum.
FD_CLOSE
Nenhum.
FD_QOS
A função WSAIoctl com SIO_GET_QOS de comando.
FD_GROUP_QOS
Reservado.
FD_ROUTING_ INTERFACE_CHANGE
A função WSAIoctl com SIO_ROUTING_INTERFACE_CHANGE de comando.
FD_ADDRESS_ LIST_CHANGE
A função WSAIoctl com SIO_ADDRESS_LIST_CHANGE de comando.
 

Qualquer chamada para a rotina de reassovamento, mesmo que falhe, resulta em nova detecção de gravação e sinalização para o evento de rede relevante e o objeto de evento.

Para eventos de rede FD_READ, FD_OOB e FD_ACCEPT, a gravação de eventos de rede e a sinalização de objeto de evento são disparadas em nível. Isso significa que, se a rotina de reação for chamada e a condição de rede relevante ainda for válida após a chamada, o evento de rede será registrado e o objeto de evento associado será definido. Isso permite que um aplicativo seja controlado por eventos e não se preocupo com a quantidade de dados que chega ao mesmo tempo. Considere a sequência a seguir:

  1. O provedor de transporte recebe 100 bytes de dados em soquetes e faz com que WS2_32.DLL registrem o evento de rede FD_READ e defina o objeto de evento associado.
  2. O aplicativo emite recv(s, buffptr, 50, 0) para ler 50 bytes.
  3. O provedor de transporte faz com que WS2_32.DLL registre o evento de rede FD_READ e define o objeto de evento associado novamente, pois ainda há dados a serem lidos.
Com essa semântica, um aplicativo não precisa ler todos os dados disponíveis em resposta a um evento de rede FD_READ — um único recv em resposta a cada evento de rede FD_READ é apropriado.

O evento FD_QOS é considerado gatilho 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 renegociar a qualidade do serviço para o soquete.

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 reemita o IOCTL e outra alteração seja detectada desde que o IOCTL tenha sido emitido.

Se um evento de rede já tiver acontecido quando o aplicativo chamar WSAEventSelect ou quando a função de nova inicialização for chamada, um evento de rede será registrado e o objeto de evento associado será definido 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 foi aceita.
  3. O aplicativo chama WSAEventSelect especificando que ele está interessado no evento de rede FD_ACCEPT para o soquete. Devido à persistência de eventos de rede, o Windows Sockets registra o evento de rede FD_ACCEPT e define o objeto de evento associado imediatamente.
O evento de rede FD_WRITE é tratado de maneira ligeiramente diferente. Um evento de rede FD_WRITE é registrado quando um soquete é conectado pela primeira vez com uma chamada para a função connect, ConnectEx, WSAConnect, WSAConnectByList ou WSAConnectByName ou quando um soquete é aceito com a função accept, AcceptEx ou WSAAccept e depois que um envio falha com WSAEWOULDBLOCK e o espaço no buffer fica disponível. Portanto, um aplicativo pode assumir que os envios são possíveis a partir do primeiro FD_WRITE configuração de evento de rede e duração até que um envio retorne WSAEWOULDBLOCK. Após essa falha, o aplicativo descobrirá que os envios são novamente possíveis quando um evento de rede FD_WRITE é registrado e o objeto de evento associado é definido.

O evento de rede 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 e obterá FD_READ evento de rede, não FD_OOB evento de rede. 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 um evento de rede FD_CLOSE indica se o fechamento do soquete foi normal ou abortivo. Se o código de erro for zero, o fechamento será normal; se o código de erro for WSAECONNRESET, o circuito virtual do soquete foi redefinido. Isso só se aplica a soquetes orientados à conexão, como SOCK_STREAM.

O evento de rede FD_CLOSE é registrado quando uma indicação próxima é recebida para o circuito virtual correspondente ao soquete. Em termos TCP, isso significa que o FD_CLOSE é registrado 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 em um closesocket. FD_CLOSE ser postado depois que todos os dados são lidos de um soquete. Um aplicativo deve marcar para os dados restantes após o recebimento de FD_CLOSE para evitar qualquer possibilidade de perda de dados. Para obter mais informações, consulte a seção sobre Desligamento Normal, Opções Persistentes e Fechamento de Soquete e a função de desligamento .

Observe que o Windows Sockets gravará apenas um evento de rede FD_CLOSE para indicar o fechamento de um circuito virtual. Ele não gravará um evento de rede FD_READ para indicar essa condição.

O evento de rede FD_QOS ou FD_GROUP_QOS é registrado quando qualquer parâmetro na especificação de fluxo associado a soquetes. Os aplicativos devem usar WSAIoctl com SIO_GET_QOS de comando para obter a qualidade atual do serviço para soquetes s.

O evento de rede FD_ROUTING_INTERFACE_CHANGE é registrado quando a interface local que deve ser usada para alcançar o destino especificado em WSAIoctl com SIO_ROUTING_INTERFACE_CHANGE alterações após a emissão desse IOCTL.

O evento de rede FD_ADDRESS_LIST_CHANGE é registrado quando a lista de endereços da família de protocolos para o soquete ao qual o aplicativo pode associar alterações após o WSAIoctl com SIO_ADDRESS_LIST_CHANGE tiver sido emitido.

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 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.

Comentários

A função WSAEventSelect é usada para especificar um objeto de evento, hEventObject, a ser associado ao FD_XXX eventos de rede selecionados, lNetworkEvents. O soquete para o qual um objeto de evento é especificado é identificado pelo parâmetro s . O objeto de evento é definido quando ocorrem qualquer um dos eventos de rede indicados.

A função WSAEventSelect opera de forma muito semelhante a WSAAsyncSelect, sendo a diferença as ações executadas quando ocorre um evento de rede indicado. A função WSAAsyncSelect faz com que uma mensagem do Windows especificada pelo aplicativo seja postada. O WSAEventSelect define o objeto de evento associado e registra a ocorrência desse evento em um registro de evento de rede interno. Um aplicativo pode usar WSAWaitForMultipleEvents para aguardar ou sondar o objeto de evento e usar WSAEnumNetworkEvents para recuperar o conteúdo do registro de evento de rede interno e, portanto, determinar qual dos eventos de rede indicados ocorreu.

A maneira adequada de redefinir o estado de um objeto de evento usado com a função WSAEventSelect é passar o identificador do objeto de evento para a função WSAEnumNetworkEvents no parâmetro hEventObject . Isso redefinirá o objeto de evento e ajustará o status de eventos FD ativos no soquete de maneira atômica.

WSAEventSelect é a única função que faz com que a atividade de rede e os erros sejam registrados e recuperáveis por meio de WSAEnumNetworkEvents. Confira as descrições de select e WSAAsyncSelect para descobrir como essas funções relatam erros e atividades de rede.

A função WSAEventSelect define automaticamente o soquete s para o modo sem bloqueio, independentemente do valor de lNetworkEvents. Para definir o soquete de volta para o modo de bloqueio, primeiro é necessário limpar o registro de evento associado ao soquete s por meio de uma chamada para WSAEventSelect com lNetworkEvents definido como zero e o parâmetro hEventObject definido como NULL. Em seguida, você pode chamar ioctlsocket ou WSAIoctl para definir o soquete de volta para o modo de bloqueio.

O parâmetro lNetworkEvents é construído usando o operador OR bit a bit com qualquer um dos valores especificados na lista a seguir.

Valor Significado
FD_READ Deseja 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 uma notificação de soquete (alterações de QoS.
FD_GROUP_QOS Reservado para uso futuro com grupos de soquetes. Deseja receber uma notificação de alterações de QoS do grupo de soquetes.
FD_ROUTING_ INTERFACE_CHANGE Deseja receber uma notificação de alterações de interface de roteamento para o destino especificado.
FD_ADDRESS_ LIST_CHANGE Deseja receber uma notificação de alterações na lista de endereços local para a família de endereços do soquete.
 

A emissão de um WSAEventSelect para um soquete cancela qualquer WSAAsyncSelect ou WSAEventSelect anterior para o mesmo soquete e limpa o registro de evento de rede interno. Por exemplo, para associar um objeto de evento a eventos de rede de leitura e gravação, o aplicativo deve chamar WSAEventSelect com FD_READ e FD_WRITE, da seguinte maneira:

rc = WSAEventSelect(s, hEventObject, FD_READ|FD_WRITE);

Não é possível especificar objetos de evento diferentes para eventos de rede diferentes. O código a seguir não funcionará; a segunda chamada cancelará os efeitos do primeiro e somente o evento de rede FD_WRITE será associado a hEventObject2:

rc = WSAEventSelect(s, hEventObject1, FD_READ);
rc = WSAEventSelect(s, hEventObject2, FD_WRITE); //bad

Para cancelar a associação e a seleção de eventos de rede em um soquete, lNetworkEvents deve ser definido como zero; nesse caso, o parâmetro hEventObject será ignorado.

rc = WSAEventSelect(s, hEventObject, 0);

Fechar um soquete com closesocket também cancela a associação e a seleção de eventos de rede especificados em WSAEventSelect para o soquete. O aplicativo, no entanto, ainda deve chamar WSACloseEvent para fechar explicitamente o objeto de evento e liberar todos os recursos.

O soquete criado quando a função accept é chamada tem as mesmas propriedades que o soquete de escuta usado para aceitá-lo. Qualquer associação WSAEventSelect e a seleção de eventos de rede definidas para o soquete de escuta se aplicam ao soquete aceito. Por exemplo, se um soquete de escuta tiver a associação WSAEventSelect de hEventObject com FD_ACCEPT, FD_READ e FD_WRITE, qualquer soquete aceito nesse soquete de escuta também terá FD_ACCEPT, FD_READ e FD_WRITE eventos de rede associados ao mesmo hEventObject. Se um hEventObject ou eventos de rede diferentes forem desejados, o aplicativo deverá chamar WSAEventSelect, passando o soquete aceito e as novas informações desejadas.

Código de exemplo

O exemplo a seguir demonstra o uso da função WSAEventSelect .
//-------------------------
// Declare and initialize variables
SOCKET ListenSocket;
WSAEVENT NewEvent;
sockaddr_in InetAddr;

//-------------------------
// Initialize listening socket
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

//-------------------------
// Bind listening socket
InetAddr.sin_family = AF_INET;
InetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InetAddr.sin_port = htons(27015);

bind (ListenSocket, (SOCKADDR *) &InetAddr, sizeof(InetAddr));

//-------------------------
// Create new event
NewEvent = WSACreateEvent();

//-------------------------
// Associate event types FD_ACCEPT and FD_CLOSE
// with the listening socket and NewEvent
WSAEventSelect( ListenSocket, NewEvent, FD_ACCEPT | FD_CLOSE);

//----------------------
// Listen for incoming connection requests 
// on the created socket
if (listen( ListenSocket, SOMAXCONN ) == SOCKET_ERROR)
    printf("Error listening on socket.\n");

printf("Listening on socket...\n");

// Need an event handler added to handle connection requests



Windows Phone 8: essa função tem suporte para aplicativos da Windows Phone Store no Windows Phone 8 e posterior.

Windows 8.1 e Windows Server 2012 R2: essa função tem suporte para aplicativos da Windows Store em Windows 8.1, Windows Server 2012 R2 e posteriores.

Requisitos

Requisito Valor
Cliente mínimo com suporte Windows 8.1, Windows Vista [aplicativos da área de trabalho | Aplicativos UWP]
Servidor mínimo com suporte Windows Server 2003 [aplicativos da área de trabalho | Aplicativos UWP]
Plataforma de Destino Windows
Cabeçalho winsock2.h
Biblioteca Ws2_32.lib
DLL Ws2_32.dll

Confira também

WSAAsyncSelect

WSACloseEvent

Wsacreateevent

WSAEnumNetworkEvents

WSAWaitForMultipleEvents

Funções Winsock

Referência de Winsock

shutdown