Função WSAAccept (winsock2.h)

A função WSAAccept aceita condicionalmente uma conexão com base no valor retornado de uma função de condição, fornece qualidade das especificações de fluxo de serviço e permite a transferência de dados de conexão.

Sintaxe

SOCKET WSAAPI WSAAccept(
  [in]      SOCKET          s,
  [out]     sockaddr        *addr,
  [in, out] LPINT           addrlen,
  [in]      LPCONDITIONPROC lpfnCondition,
  [in]      DWORD_PTR       dwCallbackData
);

Parâmetros

[in] s

Um descritor que identifica um soquete que está escutando conexões após uma chamada para a função de escuta .

[out] addr

Um ponteiro opcional para uma estrutura sockaddr que recebe o endereço da entidade de conexão, conforme conhecido pela camada de comunicações. O formato exato do parâmetro addr é determinado pela família de endereços estabelecida quando o soquete foi criado.

[in, out] addrlen

Um ponteiro opcional para um inteiro que contém o comprimento da estrutura sockaddr apontada pelo parâmetro addr , em bytes.

[in] lpfnCondition

O endereço de uma função de condição opcional especificada pelo aplicativo que tomará uma decisão de aceitação/rejeição com base nas informações do chamador passadas como parâmetros e, opcionalmente, criará ou ingressará em um grupo de soquetes atribuindo um valor apropriado ao parâmetro de resultado g dessa função. Se esse parâmetro for NULL, nenhuma função de condição será chamada.

[in] dwCallbackData

Dados de retorno de chamada passados de volta para a função de condição especificada pelo aplicativo como o valor do parâmetro dwCallbackData passado para a função de condição. Esse parâmetro só será aplicável se o parâmetro lpfnCondition não for NULL. Esse parâmetro não é interpretado pelo Windows Sockets.

Retornar valor

Se nenhum erro ocorrer, WSAAccept retornará um valor do tipo SOCKET que é um descritor para o soquete aceito. Caso contrário, um valor de INVALID_SOCKET é retornado e um código de erro específico pode ser recuperado chamando WSAGetLastError.

O inteiro referenciado por addrlen inicialmente contém a quantidade de espaço apontada pelo complemento. No retorno, ele conterá o comprimento real em bytes do endereço retornado.

Código do erro Significado
WSAEACCES
Houve uma tentativa de acesso não autorizado a um soquete conforme as permissões de acesso. Esse erro será retornado se a solicitação de conexão oferecida tiver cronometrado ou sido retirada.
WSAECONNREFUSED
Nenhuma conexão pôde ser estabelecida porque o computador de destino a recusou ativamente. Esse erro será retornado se a solicitação de conexão tiver sido rejeitada com força, conforme indicado no valor retornado da função de condição (CF_REJECT).
WSAECONNRESET
uma conexão existente foi fechada forçadamente pelo host remoto. Esse erro é retornado de uma conexão de entrada indicada, mas foi posteriormente encerrado pelo par remoto antes de aceitar a chamada.
WSAEFAULT
O sistema detectou um endereço de ponteiro inválido ao tentar usar um argumento de ponteiro em uma chamada. Esse erro é retornado do parâmetro addrlen é muito pequeno ou o addr ou lpfnCondition não faz parte do espaço de endereço do usuário.
WSAEINTR
Uma operação de bloqueio foi interrompida por uma chamada para WSACancelBlockingCall. Esse erro será retornado se uma chamada do Windows Sockets 1.1 de bloqueio tiver sido cancelada por meio de WSACancelBlockingCall.
WSAEINPROGRESS
Uma operação de bloqueio está atualmente em execução. Esse erro será retornado se uma chamada do Windows Sockets 1.1 de bloqueio estiver em andamento.
WSAEINVAL
Foi fornecido um argumento inválido. Esse erro será retornado se listen não tiver sido invocado antes de WSAAccept, o valor retornado da função de condição não for válido ou qualquer caso em que o soquete especificado esteja em um estado inválido.
WSAEMFILE
Número excessivo de soquetes abertos. Esse erro será retornado se a fila não estiver vazia após a entrada no WSAAccept e não houver descritores de soquete disponíveis.
WSAENETDOWN
Uma operação de soquete encontrou uma rede inoperante. Esse erro será retornado se o subsistema de rede falhar.
WSAENOBUFS
Não foi possível executar uma operação em um soquete porque o sistema não tinha espaço suficiente no buffer ou porque uma fila estava cheia. Esse erro será retornado se nenhum espaço de buffer estiver disponível.
WSAENOTSOCK
Houve uma tentativa de executar uma operação em algo que não é um soquete. Esse erro será retornado se o descritor de soquete passado no parâmetro s não for um soquete.
WSAEOPNOTSUPP
A família de protocolos não foi configurada no sistema ou não existe nenhuma implementação para ela. Esse erro será retornado se o soquete referenciado não for um tipo que dê suporte ao serviço orientado à conexão.
WSAEWOULDBLOCK
Não foi possível concluir imediatamente uma operação de soquete sem bloqueio. Esse erro será retornado se o soquete estiver marcado como não desbloqueado e nenhuma conexão estiver presente para ser aceita.
WSANOTINITIALISED
O aplicativo não chamou WSAStartup ou WSAStartup falhou. Esse erro é retornado de uma chamada bem-sucedida para a função WSAStartup que não ocorre antes de usar essa função.
WSATRY_AGAIN
Esse é geralmente um erro temporário durante a resolução do nome do host e significa que o servidor local não recebeu uma resposta de um servidor autorizado. Esse erro será retornado se a aceitação da solicitação de conexão tiver sido adiada conforme indicado no valor retornado da função de condição (CF_DEFER).

Comentários

A função WSAAccept extrai a primeira conexão na fila de conexões pendentes no soquete e a verifica na função de condição, desde que a função de condição seja especificada (ou seja, não NULL). Se a função de condição retornar CF_ACCEPT, o WSAAccept criará um novo soquete. O soquete recém-criado tem as mesmas propriedades que soquetes, incluindo eventos assíncronos registrados com WSAAsyncSelect ou com WSAEventSelect. Se a função de condição retornar CF_REJECT, o WSAAccept rejeitará a solicitação de conexão. A função de condição é executada no mesmo thread que essa função e deve retornar o mais rápido possível. Se a decisão não puder ser tomada imediatamente, a função de condição deverá retornar CF_DEFER para indicar que nenhuma decisão foi tomada e nenhuma ação sobre essa solicitação de conexão deve ser tomada pelo provedor de serviços. Quando o aplicativo estiver pronto para executar uma ação na solicitação de conexão, ele invocará WSAAccept novamente e retornará CF_ACCEPT ou CF_REJECT como um valor retornado da função de condição.

Um soquete no modo padrão (bloqueio) será bloqueado até que uma conexão esteja presente quando um aplicativo chamar WSAAccept e nenhuma conexão estiver pendente na fila.

Um soquete no modo sem bloqueio (bloqueio) falha com o erro WSAEWOULDBLOCK quando um aplicativo chama WSAAccept e nenhuma conexão está pendente na fila. Depois que o WSAAccept for bem-sucedido e retornar um novo identificador de soquete, o soquete aceito não poderá ser usado para aceitar mais conexões. O soquete original permanece aberto e escuta novas solicitações de conexão.

O parâmetro addr é um parâmetro de resultado preenchido com o endereço da entidade de conexão, conforme conhecido pela camada de comunicações. O formato exato do parâmetro addr é determinado pela família de endereços na qual a comunicação está ocorrendo. O addrlen é um parâmetro value-result; inicialmente, ele deve conter a quantidade de espaço apontada pelo complemento. No retorno, ele conterá o comprimento real (em bytes) do endereço retornado. Essa chamada é usada com tipos de soquete orientados à conexão, como SOCK_STREAM. Se addr e/ou addrlen forem iguais a NULL, nenhuma informação sobre o endereço remoto do soquete aceito será retornada. Caso contrário, esses dois parâmetros serão preenchidos se a conexão for aceita com êxito.

Um protótipo da função de condição é definido no arquivo de Winsock2.h cabeçalho como LPCONDITIONPROC, da seguinte maneira.

int CALLBACK 
ConditionFunc( 
  IN     LPWSABUF    lpCallerId, 
  IN     LPWSABUF    lpCallerData, 
  IN OUT LPQOS       lpSQOS, 
  IN OUT LPQOS       lpGQOS,
  IN     LPWSABUF    lpCalleeId, 
  IN     LPWSABUF    lpCalleeData, 
  OUT    GROUP FAR * g, 	
  IN     DWORD_PTR   dwCallbackData
);

ConditionFunc é um espaço reservado para a função de retorno de chamada especificada pelo aplicativo. A função de condição real deve residir em um módulo de DLL ou aplicativo. Ele é exportado no arquivo de definição do módulo.

O parâmetro lpCallerId aponta para uma estrutura WSABUF que contém o endereço da entidade de conexão, em que seu parâmetro len é o comprimento do buffer em bytes e seu parâmetro buf é um ponteiro para o buffer. O lpCallerData é um parâmetro de valor que contém todos os dados do usuário. As informações nesses parâmetros são enviadas junto com a solicitação de conexão. Se nenhum dado de chamada ou identificação de chamador estiver disponível, os parâmetros correspondentes serão NULL. Muitos protocolos de rede não dão suporte a dados do chamador de tempo de conexão. Espera-se que a maioria dos protocolos de rede convencionais dê suporte a informações de identificador de chamador no momento da solicitação de conexão. A parte buf do WSABUF apontada por lpCallerId aponta para um sockaddr. A estrutura sockaddr é interpretada de acordo com sua família de endereços (normalmente, convertendo o sockaddr em algum tipo específico para a família de endereços).

O parâmetro lpSQOS faz referência às estruturas FLOWSPEC para soquetes especificados pelo chamador, um para cada direção, seguido por parâmetros específicos do provedor adicionais. Os valores de especificação de fluxo de envio ou recebimento serão ignorados conforme apropriado para quaisquer soquetes unidirecionais. Um valor NULL indica que não há qualidade de serviço fornecida pelo chamador e que nenhuma negociação é possível. Um ponteiro lpSQOS não NULL indica que uma negociação de qualidade de serviço deve ocorrer ou que o provedor está preparado para aceitar a qualidade da solicitação de serviço sem negociação.

O parâmetro lpGQOS é reservado e deve ser NULL. (reservado para uso futuro com grupos de soquetes) faz referência à estrutura FLOWSPEC para o grupo de soquetes que o chamador deve criar, uma para cada direção, seguida por parâmetros adicionais específicos do provedor. Um valor NULL para lpGQOS indica nenhuma qualidade de serviço de grupo especificada pelo chamador. As informações de qualidade do serviço poderão ser retornadas se a negociação ocorrer.

O lpCalleeId é um parâmetro que contém o endereço local da entidade conectada. A parte buf do WSABUF apontada por lpCalleeId aponta para uma estrutura sockaddr . A estrutura sockaddr é interpretada de acordo com sua família de endereços (normalmente, convertendo o sockaddr em algum tipo específico para a família de endereços, como struct sockaddr_in).

O lpCalleeData é um parâmetro de resultado usado pela função de condição para fornecer dados do usuário de volta à entidade de conexão. O lpCalleeData-len> inicialmente contém o comprimento do buffer alocado pelo provedor de serviços e apontado por lpCalleeData-buf>. Um valor zero significa que não há suporte para a passagem de dados do usuário para o chamador. A função de condição deve copiar até lpCalleeData-len> bytes de dados para lpCalleeData-buf> e, em seguida, atualizar lpCalleeData-len> para indicar o número real de bytes transferidos. Se nenhum dado do usuário for passado de volta para o chamador, a função de condição deverá definir lpCalleeData-len> como zero. O formato de todos os dados de endereço e de usuário é específico para a família de endereços à qual o soquete pertence.

O parâmetro g é atribuído dentro da função de condição para indicar qualquer uma das seguintes ações:

  • Se g for um identificador de grupo de soquetes existente, adicione s a esse grupo, desde que todos os requisitos definidos por esse grupo sejam atendidos.
  • Se g = SG_UNCONSTRAINED_GROUP, crie um grupo de soquetes não treinado e tenha s como o primeiro membro.
  • Se g = SG_CONSTRAINED_GROUP, crie um grupo de soquetes restrito e tenha s como o primeiro membro.
  • Se g = zero, nenhuma operação de grupo será executada.
Para grupos não treinados, qualquer conjunto de soquetes pode ser agrupado desde que eles sejam compatíveis com um único provedor de serviços. Um grupo de soquetes restrito pode consistir apenas em soquetes orientados à conexão e requer que as conexões em todos os soquetes agrupados sejam para o mesmo endereço no mesmo host. Para grupos de soquetes recém-criados, o novo identificador de grupo pode ser recuperado usando a função getsockopt com o parâmetro level definido como SOL_SOCKET e o parâmetro optname definido como SO_GROUP_ID. Um grupo de soquetes e sua ID de grupo de soquete associado permanecem válidos até que o último soquete pertencente a esse grupo de soquetes seja fechado. As IDs de grupo de soquete são exclusivas em todos os processos para um determinado provedor de serviços. Um grupo de soquetes e seu identificador associado permanecem válidos até que o último soquete pertencente a esse grupo de soquetes seja fechado. Os identificadores de grupo de soquetes são exclusivos em todos os processos para um determinado provedor de serviços. Para obter mais informações sobre grupos de soquetes, consulte Comentários para as funções WSASocket .

O valor do parâmetro dwCallbackData passado para a função de condição é o valor passado como o parâmetro dwCallbackData na chamada WSAAccept original. Esse valor é interpretado apenas pelo cliente do Windows Socket versão 2. Isso permite que um cliente passe algumas informações de contexto do site de chamada WSAAccept para a função de condição. Isso também fornece à função de condição quaisquer informações adicionais necessárias para determinar se a conexão deve ser aceita ou não. Um uso típico é passar um ponteiro (adequadamente convertido) para uma estrutura de dados que contém referências a objetos definidos pelo aplicativo com os quais esse soquete está associado.

Nota Para proteger o uso da função WSAAccept contra ataques SYN, os aplicativos devem executar handshakes TCP completos (SYN-SYNACK-ACK) antes de relatar a solicitação de conexão. A proteção contra ataques SYN dessa maneira faz com que a opção de soquete SO_CONDITIONAL_ACCEPT se torne inoperante; a função condicional ainda é chamada e a função WSAAccept opera corretamente, mas os aplicativos de servidor que dependem de clientes que não conseguem executar o handshake não funcionarão corretamente.
 
Nota Ao emitir uma chamada winsock de bloqueio, como WSAAccept, Winsock pode precisar aguardar um evento de rede antes que a chamada possa ser concluída. O Winsock executa uma espera alertável nessa situação, que pode ser interrompida por uma APC (chamada de procedimento assíncrona) agendada no mesmo thread. Emitir outra chamada winsock de bloqueio dentro de um APC que interrompeu uma chamada Winsock de bloqueio contínuo no mesmo thread levará a um comportamento indefinido e nunca deve ser tentado pelos clientes winsock.
 

Código de exemplo

O exemplo a seguir demonstra o uso da função WSAAccept .
#include <winsock2.h>
#include <stdio.h>
#include <windows.h>

/* Define an example conditional function that depends on the pQos field */
int CALLBACK ConditionAcceptFunc(
    LPWSABUF lpCallerId,
    LPWSABUF lpCallerData,
    LPQOS pQos,
    LPQOS lpGQOS,
    LPWSABUF lpCalleeId,
    LPWSABUF lpCalleeData,
    GROUP FAR * g,
    DWORD_PTR dwCallbackData
    )
{

    if (pQos != NULL) {
        RtlZeroMemory(pQos, sizeof(QOS));
        return CF_ACCEPT;
    } else
        return CF_REJECT;
}

int main() {

    /* Declare and initialize variables */
    WSADATA wsaData;
    SOCKET ListenSocket, AcceptSocket;
    struct sockaddr_in saClient;
    int iClientSize = sizeof(saClient);
    u_short port = 27015;
    char* ip;
    sockaddr_in service;
    int error;

    /* Initialize Winsock */
    error = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (error) {
        printf("WSAStartup() failed with error: %d\n", error);
        return 1;
    }

    /* Create a TCP listening socket */
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {  
        printf("socket() failed with error: %d\n", WSAGetLastError() );
        WSACleanup();
        return 1;
    }

    /*-----------------------------------------  
     *  Set up the sock addr structure that the listening socket
     *  will be bound to. In this case, the structure holds the
     * local IP address and the port specified. */
    service.sin_family = AF_INET;
    service.sin_port = htons(port);
    hostent* thisHost;
    thisHost = gethostbyname("");
    ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);
    service.sin_addr.s_addr = inet_addr(ip);

    /*-----------------------------------------
     *  Bind the listening socket to the IP address.
     * and port number specified by the sockaddr structure. */
    error = bind(ListenSocket, (SOCKADDR *) &service, sizeof(SOCKADDR));
    if (error == SOCKET_ERROR) {  
        printf("bind() failed with error: %d\n", WSAGetLastError() );
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
  
    /* Make the socket listen for incoming connection requests */
    error = listen(ListenSocket, 1);
    if (error == SOCKET_ERROR) {  
        printf("listen() failed with error: %d\n", WSAGetLastError() );
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    printf("Listening...\n");
  
    /*-----------------------------------------
     *  Accept an incoming connection request on the
     *  listening socket and transfer control to the 
     * accepting socket. */
    AcceptSocket = WSAAccept(ListenSocket, (SOCKADDR*) &saClient, &iClientSize, 
        &ConditionAcceptFunc, NULL);
 
    /*  Now do some work with the AcceptSocket 
     *  At this point, the application could
     *  handle data transfer on the socket, or other socket
     * functionality.*/
    
    /* Then clean up and quit */

    closesocket(AcceptSocket);
    closesocket(ListenSocket);
    WSACleanup();

    return 0;
}

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

Wsaconnect

Wsasocket

Funções Winsock

Referência de Winsock

accept

bind

connect

Getsockopt

listen

select

Sockaddr

socket