Função WSAConnectByList (winsock2.h)

A função WSAConnectByList estabelece uma conexão com uma de uma coleção de possíveis pontos de extremidade representados por um conjunto de endereços de destino (nomes de host e portas). Essa função usa todos os endereços de destino passados para ele e todos os endereços de origem do computador local e tenta se conectar usando todas as combinações de endereços possíveis antes de desistir.

Essa função dá suporte a endereços IPv4 e IPv6.

Sintaxe

BOOL WSAConnectByList(
  [in]      SOCKET               s,
  [in]      PSOCKET_ADDRESS_LIST SocketAddress,
  [in, out] LPDWORD              LocalAddressLength,
  [out]     LPSOCKADDR           LocalAddress,
  [in, out] LPDWORD              RemoteAddressLength,
  [out]     LPSOCKADDR           RemoteAddress,
  [in]      const timeval        *timeout,
  [in]      LPWSAOVERLAPPED      Reserved
);

Parâmetros

[in] s

Um descritor que identifica um soquete não associado e não conectado. Observe que, ao contrário de outras chamadas winsock para estabelecer uma conexão (por exemplo, WSAConnect), a função WSAConnectByList requer um soquete não associado.

[in] SocketAddress

Um ponteiro para uma estrutura SOCKET_ADDRESS_LIST que representa os possíveis pares de endereço de destino e porta para se conectar a um par. É responsabilidade do aplicativo preencher o número da porta na estrutura de cada SOCKET_ADDRESS no SOCKET_ADDRESS_LIST.

[in, out] LocalAddressLength

Na entrada, um ponteiro para o tamanho, em bytes, do buffer LocalAddress fornecido pelo chamador. Na saída, um ponteiro para o tamanho, em bytes, do SOCKADDR para o endereço local armazenado no buffer LocalAddress preenchido pelo sistema após a conclusão bem-sucedida da chamada.

[out] LocalAddress

Um ponteiro para a estrutura SOCKADDR que recebe o endereço local da conexão. O tamanho do parâmetro é exatamente o tamanho retornado em LocalAddressLength. Essas são as mesmas informações que seriam retornadas pela função getsockname . Esse parâmetro pode ser NULL; nesse caso, o parâmetro LocalAddressLength é ignorado.

[in, out] RemoteAddressLength

Na entrada, um ponteiro para o tamanho, em bytes, do buffer RemoteAddress fornecido pelo chamador. Na saída, um ponteiro para o tamanho, em bytes, do SOCKADDR para o endereço remoto armazenado no buffer RemoteAddress preenchido pelo sistema após a conclusão bem-sucedida da chamada.

[out] RemoteAddress

Um ponteiro para a estrutura SOCKADDR que recebe o endereço remoto da conexão. Essas são as mesmas informações que seriam retornadas pela função getpeername . Esse parâmetro pode ser NULL; nesse caso, RemoteAddressLength é ignorado.

[in] timeout

O tempo, em milissegundos, para aguardar uma resposta do aplicativo remoto antes de anular a chamada. Esse parâmetro pode ser NULL , caso em que o WSAConnectByList será concluído depois que a conexão for estabelecida com êxito ou depois que uma conexão tiver sido tentada e falhar em todos os possíveis pares de endereços local-remotos.

[in] Reserved

Reservado para implementação futura. Esse parâmetro deve ser definido como NULL.

Valor retornado

Se uma conexão for estabelecida, WSAConnectByList retornará os parâmetros TRUE e LocalAddress e RemoteAddress serão preenchidos se esses buffers forem fornecidos pelo chamador.

Se a chamada falhar, FALSE será retornado. O WSAGetLastError pode ser chamado para obter informações de erro estendidas.

Código de retorno Descrição
WSAEHOSTUNREACH
O host passado como o parâmetro nodename estava inacessível.
WSAEINVAL
Um parâmetro inválido foi passado para a função. O parâmetro Reserved deve ser NULL.
WSAENOBUFS
Não foi possível alocar memória suficiente.
WSAENOTSOCK
Um soquete inválido foi passado para a função . O parâmetro s não deve ser INVALID_SOCKET ou NULL.
WSAETIMEDOUT
Uma resposta do aplicativo remoto não foi recebida antes que o parâmetro de tempo limite fosse excedido.

Comentários

WSAConnectByList é semelhante à função WSAConnectByName . Em vez de usar um único nome de host e nome de serviço (porta), WSAConnectByList usa uma lista de endereços (endereços de host e portas) e se conecta a um dos endereços. A função WSAConnectByList foi projetada para dar suporte a cenários de colaboração ponto a ponto em que um aplicativo precisa se conectar a qualquer nó disponível fora de uma lista de nós potenciais. O WSAConnectByList é compatível com as versões IPv6 e IPv4.

O conjunto de destinos possíveis, representado por uma lista de endereços, é fornecido pelo chamador. WSAConnectByList faz mais do que simplesmente tentar se conectar a um dos endereços de destino possivelmente muitos. Especificamente, a função usa todos os endereços remotos passados pelo chamador, todos os endereços locais e, em seguida, tenta uma conexão primeiro usando pares de endereços com a maior chance de sucesso. Dessa forma, WSAConnectByList não apenas garante que a conexão será estabelecida se uma conexão for possível, mas também minimiza o tempo para estabelecer a conexão.

O chamador pode especificar os buffers e comprimentos LocalAddress e RemoteAddress para determinar os endereços locais e remotos para os quais a conexão foi estabelecida com êxito.

O parâmetro de tempo limite permite que o chamador limite o tempo gasto pela função no estabelecimento de uma conexão. Internamente, o WSAConnectByList executa várias operações (tentativas de conexão). Entre cada operação, o parâmetro de tempo limite é verificado para ver se o tempo limite foi excedido e, nesse caso, a chamada é anulada. Observe que uma operação individual (conectar) não será interrompida depois que o tempo limite for excedido, portanto, a chamada WSAConnectByList pode levar mais tempo do que o valor especificado no parâmetro de tempo limite .

WSAConnectByList tem limitações: ele funciona apenas para soquetes orientados à conexão, como aqueles do tipo SOCK_STREAM. A função não dá suporte a E/S sobreposta ou comportamento sem bloqueio. WSAConnectByList será bloqueado mesmo se o soquete estiver no modo sem bloqueio. WSAConnectByList tentará se conectar (um por um) aos vários endereços fornecidos pelo chamador. Potencialmente, cada uma dessas tentativas de conexão pode falhar com um código de erro diferente. Como apenas um único código de erro pode ser retornado, o valor retornado é o código de erro da última tentativa de conexão.

Para permitir que endereços IPv6 e IPv4 sejam passados na lista de endereços únicos aceita pela função, as seguintes etapas devem ser executadas antes de chamar a função:

  • A função setsockopt deve ser chamada em um soquete criado para a família de endereços AF_INET6 para desabilitar a opção de soquete IPV6_V6ONLY antes de chamar WSAConnectByList. Isso é feito chamando a função setsockopt no soquete com o parâmetro de nível definido como IPPROTO_IPV6 (consulte IPPROTO_IPV6 Opções de Soquete), o parâmetro optname definido como IPV6_V6ONLY e o valor do parâmetro optvalue definido como zero.
  • Todos os endereços IPv4 devem ser representados no formato de endereço IPv6 mapeado por IPv4, que permite que um aplicativo somente IPv6 se comunique com um nó IPv4. O formato de endereço IPv6 mapeado por IPv4 permite que o endereço IPv4 de um nó IPv4 seja representado como um endereço IPv6. O endereço IPv4 é codificado nos 32 bits de ordem inferior do endereço IPv6 e os 96 bits de ordem alta mantêm o prefixo fixo 0:0:0:0:0:FFFF. O formato de endereço IPv6 mapeado por IPv4 é especificado no RFC 4291. Para obter mais informações, consulte www.ietf.org/rfc/rfc4291.txt. A macro IN6ADDR_SETV4MAPPED em Mstcpip.h pode ser usada para converter um endereço IPv4 no formato de endereço IPv6 mapeado IPv4 necessário.

As matrizes de ponteiros passados no parâmetro SocketAddressList apontam para uma matriz de estruturas SOCKET_ADDRESS , que são um tipo de dados genérico. Os parâmetros RemoteAddress e LocalAddress também apontam para estruturas SOCKADDR . Quando WSAConnectByList é chamado, espera-se que um tipo de endereço de soquete específico para o protocolo de rede ou a família de endereços que está sendo usado seja realmente passado nesses parâmetros. Portanto, para endereços IPv4, um ponteiro para uma estrutura sockaddr_in seria convertido em um ponteiro para SOCKADDR quando passado como um parâmetro. Para endereços IPv6, um ponteiro para uma estrutura sockaddr_in6 seria convertido em um ponteiro para SOCKADDR quando passado como um parâmetro. O parâmetro SocketAddressList pode conter ponteiros para uma mistura de endereços IPv4 e IPv6. Portanto, alguns ponteiros SOCKET_ADDRESS podem ser para sockaddr_in estruturas e outros podem ser para sockaddr_in6 estruturas. Se for esperado que os endereços IPv6 possam ser usados, os parâmetros RemoteAddress e LocalAddress deverão apontar para sockaddr_in6 estruturas e serem convertidos em estruturas SOCKADDR . Os parâmetros RemoteAddressLength e LocalAddressLength devem representar o comprimento dessas estruturas maiores.

Quando a função WSAConnectByList retorna TRUE, o soquete s está no estado padrão de um soquete conectado. O soquete s não habilita propriedades ou opções definidas anteriormente até que SO_UPDATE_CONNECT_CONTEXT seja definido no soquete. Use a função setsockopt para definir a opção SO_UPDATE_CONNECT_CONTEXT.

Por exemplo:

//Need to #include <mswsock.h> for SO_UPDATE_CONNECT_CONTEXT

int iResult = 0;

iResult = setsockopt( s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0 );

Nota Ao emitir uma chamada winsock de bloqueio, como WSAConnectByList com o parâmetro de tempo limite definido como NULL, o 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 por clientes Winsock.
 
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 posterior.

Exemplos

Estabeleça uma conexão usando WSAConnectByList.

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")


SOCKET
OpenAndConnect(SOCKET_ADDRESS_LIST *AddressList) 
{
    SOCKET ConnSocket = INVALID_SOCKET;

    int ipv6only = 0;
    int iResult;
    BOOL bSuccess;

    SOCKADDR_STORAGE LocalAddr = {0};
    SOCKADDR_STORAGE RemoteAddr = {0};

    DWORD dwLocalAddr = sizeof(LocalAddr);
    DWORD dwRemoteAddr = sizeof(RemoteAddr);

    ConnSocket = socket(AF_INET6, SOCK_STREAM, 0);
    if (ConnSocket == INVALID_SOCKET){
        return INVALID_SOCKET;
    }

    iResult = setsockopt(ConnSocket, IPPROTO_IPV6,
        IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
    if (iResult == SOCKET_ERROR){
        closesocket(ConnSocket);
        return INVALID_SOCKET;       
    }

    // AddressList may contain IPv6 and/or IPv4Mapped addresses
    bSuccess = WSAConnectByList(ConnSocket,
            AddressList,
            &dwLocalAddr,
            (SOCKADDR*)&LocalAddr,
            &dwRemoteAddr,
            (SOCKADDR*)&RemoteAddr,
            NULL,
            NULL);
    if (bSuccess){
        return ConnSocket;
    } else {
        return INVALID_SOCKET;
    }
}

Requisitos

   
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

Opções de soquete IPPROTO_IPV6

SOCKADDR

SOCKET_ADDRESS

SOCKET_ADDRESS_LIST

Wsaconnect

WSAConnectByName

Wsagetlasterror

Getaddrinfo

Getpeername

Getsockname

Setsockopt