Compartilhar via


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 o escuta função.

[out] addr

Um ponteiro opcional para uma estrutura de sockaddr que recebe o endereço da entidade de conexão, conforme conhecido pela camada de comunicações. O formato exato do parâmetro do suplemento é 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 de de soquete apontado pelo parâmetro do 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 de 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 pelos Soquetes do Windows.

Valor de retorno

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 contém inicialmente a quantidade de espaço apontada por do suplemento. Ao retornar, ele conterá o comprimento real em bytes do endereço retornado.

Código de erro Significado
WSAEACCES
Foi feita uma tentativa de acessar um soquete de forma proibida por suas permissões de acesso. Esse erro será retornado se a solicitação de conexão oferecida tiver ultrapassado ou sido retirada.
WSAECONNREFUSED
Nenhuma conexão poderia ser feita 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ça pelo host remoto. Esse erro é retornado de uma conexão de entrada foi indicado, mas posteriormente foi 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 do 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á sendo executada no momento. Esse erro será retornado se uma chamada de bloqueio do Windows Sockets 1.1 estiver em andamento.
WSAEINVAL
Um argumento inválido foi fornecido. Esse erro será retornado se escuta 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
Soquetes abertos demais. Esse erro será retornado se a fila não estiver cheia após a entrada para WSAAccept e não houver descritores de soquete disponíveis.
WSAENETDOWN
Uma operação de soquete encontrou uma rede morta. 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
Uma operação foi tentada em algo que não é um soquete. Esse erro será retornado se o descritor de soquete passado no parâmetro do 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
Uma operação de soquete sem bloqueio não pôde ser concluída imediatamente. 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 não ocorrer antes de usar essa função.
WSATRY_AGAIN
Isso geralmente é um erro temporário durante a resolução de nome de host e significa que o servidor local não recebeu uma resposta de um servidor autoritativo. 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).

Observações

A função WSAAccept extrai a primeira conexão na fila de conexões pendentes no soquete e verifica-a 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 condição retornar CF_ACCEPT, WSAAccept criará um novo soquete. O soquete recém-criado tem as mesmas propriedades do soquete incluindo eventos assíncronos registrados com WSAAsyncSelect ou com WSAEventSelect. Se a função de condição retornar CF_REJECT, 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 deverá 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 de não bloqueio (bloqueio) falha com o erro WSAEWOULDBLOCK quando um aplicativo chama WSAAccept e nenhuma conexão está pendente na fila. Depois que WSAAccept é bem-sucedido e retorna um novo identificador de soquete, o soquete aceito não pode ser usado para aceitar mais conexões. O soquete original permanece aberto e escuta novas solicitações de conexão.

O parâmetro do suplemento é 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 do suplemento é determinado pela família de endereços na qual a comunicação está ocorrendo. O addrlen é um parâmetro de valor-resultado; inicialmente, ele deve conter a quantidade de espaço apontada por do 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 do suplemento e/ou de complemento 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 cabeçalho Winsock2.h 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
);

O 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 uma DLL ou módulo de 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, onde 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 de chamadas em tempo de conexão. A maioria dos protocolos de rede convencionais pode ser esperada para dar suporte a informações de identificador de chamador no momento da solicitação de conexão. A parte buf da WSABUF apontada por lpCallerId aponta para umde sockaddr . A estrutura de de soquete é interpretada de acordo com sua família de endereços (normalmente, lançando o sockaddr para algum tipo específico para a família de endereços).

O parâmetro lpSQOS faz referência às estruturas de FLOWSPEC para de de soquete especificadas pelo chamador, uma para cada direção, seguida por parâmetros adicionais específicos do provedor. Os valores de especificação de fluxo de envio ou recebimento serão ignorados conforme apropriado para quaisquer soquetes unidirecionais. Um valor de NULL indica que não há qualidade de serviço fornecida pelo chamador e que nenhuma negociação é possível. Um ponteiroNULL nãoindica 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, um para cada direção, seguido por parâmetros adicionais específicos do provedor. Um valor de 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 de de soquete . A estrutura de de soquete é interpretada de acordo com sua família de endereços (normalmente, lançando o de soquete para 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 em lpCalleeData->bufe, 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 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 como o primeiro membro.
  • Se g = SG_CONSTRAINED_GROUP, crie um grupo de soquetes restrito e tenha 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 estejam no mesmo endereço no mesmo host. Para grupos de soquetes recém-criados, o novo identificador de grupo pode ser recuperado usando função de getsockopt com nível parâmetro definido como SOL_SOCKET e o parâmetro optname definido como SO_GROUP_ID. Um grupo de soquetes e sua ID de grupo de soquetes associados 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 as Observações para as funções de do 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 de 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 chamadas do WSAAccept para a função de condição. Isso também fornece a função de condição com 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.

Observação 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. Proteger contra ataques SYN dessa maneira resulta na opção de soquete SO_CONDITIONAL_ACCEPT se tornando 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.
 
Observação 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íncrono) agendada no mesmo thread. A emissão de 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 tentada 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 no Windows 8.1, Windows Server 2012 R2 e posterior.

Requisitos

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

Consulte também

WSAAsyncSelect

WSAConnect

WSASocket

do Winsock Functions

referência Winsock

aceitar

associar

conectar

de getsockopt

escuta

selecione

de soquete

soquete