Compartilhar via


Função WSAConnectByNameW (winsock2.h)

A função WSAConnectByName estabelece uma conexão com um host e uma porta especificados. Essa função é fornecida para permitir uma conexão rápida com um ponto de extremidade de rede, considerando um nome de host e uma porta.

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

Sintaxe

BOOL WSAConnectByNameW(
  [in]      SOCKET          s,
  [in]      LPWSTR          nodename,
  [in]      LPWSTR          servicename,
  [in, out] LPDWORD         LocalAddressLength,
  [out]     LPSOCKADDR      LocalAddress,
  [in, out] LPDWORD         RemoteAddressLength,
  [out]     LPSOCKADDR      RemoteAddress,
  [in]      const timeval   *timeout,
            LPWSAOVERLAPPED Reserved
);

Parâmetros

[in] s

Um descritor que identifica um soquete não conectado.

Nota No Windows 7, Windows Server 2008 R2 e versões anteriores, a função WSAConnectByName requer um soquete não associado e não conectado. Isso difere de outras chamadas winsock para estabelecer uma conexão (por exemplo, WSAConnect).
 

[in] nodename

Uma cadeia de caracteres terminada em NULL que contém o nome do host ou o endereço IP do host no qual se conectar para IPv4 ou IPv6.

[in] servicename

Uma cadeia de caracteres terminada em NULL que contém o nome do serviço ou a porta de destino do host no qual se conectar para IPv4 ou IPv6.

Um nome de serviço é um alias de cadeia de caracteres para um número de porta. Por exemplo, "http" é um alias para a porta 80 definido pela IETF (Internet Engineering Task Force) como a porta padrão usada pelos servidores Web para o protocolo HTTP. Os valores possíveis para o parâmetro servicename quando um número de porta não é especificado são listados no seguinte arquivo:

%WINDIR%\system32\drivers\etc\services

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

Reserved

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

Retornar valor

Se uma conexão for estabelecida, WSAConnectByName 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 nodename ou servicename não deve ser NULL. 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

O WSAConnectByName é fornecido para habilitar conexões rápidas e transparentes com hosts remotos em portas específicas. Ele é compatível com as versões IPv6 e IPv4.

Para habilitar as comunicações IPv6 e IPv4, use o seguinte método:

  • A função setsockopt deve ser chamada em um soquete criado para a família de endereços AF_INET6 desabilitar a opção de soquete IPV6_V6ONLY antes de chamar WSAConnectByName. 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.

O WSAConnectByName tem limitações: 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. WSAConnectByName será bloqueado mesmo se o soquete estiver no modo sem bloqueio.

O WSAConnectByName não dá suporte a dados fornecidos pelo usuário durante o estabelecimento de uma conexão. Essa chamada também não dá suporte a estruturas FLOWSPEC. Nos casos em que esses recursos são necessários, o WSAConnect deve ser usado.

Em versões antes de Windows 10, se um aplicativo precisar ser associado a um endereço ou porta local específico, o WSAConnectByName não poderá ser usado, pois o parâmetro de soquete para WSAConnectByName deve ser um soquete não associado.

Essa restrição foi removida Windows 10.

Os parâmetros RemoteAddress e LocalAddress apontam para uma estrutura SOCKADDR , que é um tipo de dados genérico. Quando WSAConnectByName é chamado, espera-se que um tipo de endereço de soquete específico para o protocolo de rede ou 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 como os parâmetros RemoteAddress e LocalAddress . Para endereços IPv6, um ponteiro para uma estrutura sockaddr_in6 seria convertido em um ponteiro para SOCKADDR como os parâmetros RemoteAddress e LocalAddress .

Quando a função WSAConnectByName 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 WSAConnectByName 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: a função WSAConnectByNameW tem suporte para aplicativos da Windows Phone Store no Windows Phone 8 e posterior.

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

Exemplos

Estabeleça uma conexão usando WSAConnectByName.

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <mswsock.h>   // Need for SO_UPDATE_CONNECT_CONTEXT
#include <stdio.h>

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

SOCKET
OpenAndConnect(LPWSTR NodeName, LPWSTR PortName) 
{
    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){
        wprintf(L"socket failed with error: %d\n", WSAGetLastError());
        return INVALID_SOCKET;
    }

    iResult = setsockopt(ConnSocket, IPPROTO_IPV6,
        IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
    if (iResult == SOCKET_ERROR){
        wprintf(L"setsockopt for IPV6_V6ONLY failed with error: %d\n",
            WSAGetLastError());
        closesocket(ConnSocket);
        return INVALID_SOCKET;       
    }

    bSuccess = WSAConnectByName(ConnSocket, NodeName, 
            PortName, &dwLocalAddr,
            (SOCKADDR*)&LocalAddr,
            &dwRemoteAddr,
            (SOCKADDR*)&RemoteAddr,
            NULL,
            NULL);
    if (!bSuccess){
        wprintf(L"WsaConnectByName failed with error: %d\n", WSAGetLastError());
        closesocket(ConnSocket);
        return INVALID_SOCKET;       

    
    }

    iResult = setsockopt(ConnSocket, SOL_SOCKET,
        SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
    if (iResult == SOCKET_ERROR){
        wprintf(L"setsockopt for SO_UPDATE_CONNECT_CONTEXT failed with error: %d\n",
            WSAGetLastError());
        closesocket(ConnSocket);
        return INVALID_SOCKET;       
    }

    return ConnSocket;
}

int __cdecl wmain(int argc, wchar_t **argv)
{
   //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult;

    SOCKET s = INVALID_SOCKET;

    // Validate the parameters
    if (argc != 3) {
        wprintf(L"usage: %ws <Nodename> <Portname>\n", argv[0]);
        wprintf(L"wsaconnectbyname establishes a connection to a specified host and port.\n");
        wprintf(L"%ws www.contoso.com 8080\n", argv[0]);
        return 1;
    }

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        wprintf(L"WSAStartup failed: %d\n", iResult);
        return 1;
    }

    wprintf(L"WsaConnectByName with following parameters:\n");
    wprintf(L"\tNodename = %ws\n", argv[1]);
    wprintf(L"\tPortname (or port) = %ws\n\n", argv[2]);

    //--------------------------------
    // Call our function that uses the WsaConnectByName. 
    
    s = OpenAndConnect(argv[1], argv[2]);
    if ( s == INVALID_SOCKET ) {
        wprintf(L"WsaConnectByName failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    else
    {
        wprintf(L"WsaConnectByName succeeded\n");
        
        closesocket(s);
        WSACleanup();
        return 0;
    }
}

Observação

O cabeçalho winsock2.h define WSAConnectByName como um alias que seleciona automaticamente a versão ANSI ou Unicode dessa função com base na definição da constante de pré-processador UNICODE. Misturar o uso do alias neutro de codificação com código que não seja neutro em codificação pode levar a incompatibilidades que resultam em erros de compilação ou de runtime. Para obter mais informações, consulte Convenções para protótipos de função.

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 2008 [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

Wsaconnect

WSAConnectByList

Wsagetlasterror

Getaddrinfo

Getpeername

Getsockname

Setsockopt