Поделиться через


Функция WSAConnectByNameA (winsock2.h)

Функция WSAConnectByName устанавливает соединение с указанным узлом и портом. Эта функция предоставляется для быстрого подключения к конечной точке сети с учетом имени узла и порта.

Эта функция поддерживает адреса IPv4 и IPv6.

Синтаксис

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

Параметры

[in] s

Дескриптор, идентифицирующий несвязанный сокет.

Примечание В Windows 7, Windows Server 2008 R2 и более ранних версиях для функции WSAConnectByName требуется несвязанный и несвязанный сокет. Это отличается от других вызовов Winsock для установки подключения (например, WSAConnect).
 

[in] nodename

Строка, завершающаяся значением NULL, которая содержит имя узла или IP-адрес узла, к которому нужно подключиться для IPv4 или IPv6.

[in] servicename

Строка с завершением NULL, содержащая имя службы или порт назначения узла, к которому нужно подключиться для IPv4 или IPv6.

Имя службы — это строковый псевдоним для номера порта. Например, "http" — это псевдоним порта 80, определенный целевой группой по проектированию в Интернете (IETF) в качестве порта по умолчанию, используемого веб-серверами для протокола HTTP. Возможные значения параметра servicename , если номер порта не указан, перечислены в следующем файле:

%WINDIR%\system32\drivers\etc\services

[in, out] LocalAddressLength

На входных данных — указатель на размер буфера LocalAddress в байтах , предоставленного вызывающим объектом. В выходных данных — указатель на размер (в байтах) SOCKADDR для локального адреса, хранящегося в буфере LocalAddress , заполненном системой после успешного завершения вызова.

[out] LocalAddress

Указатель на структуру SOCKADDR , которая получает локальный адрес подключения. Размер параметра точно совпадает с размером, возвращенным в LocalAddressLength. Это те же сведения, которые будут возвращены функцией getsockname . Этот параметр может иметь значение NULL. В этом случае параметр LocalAddressLength игнорируется.

[in, out] RemoteAddressLength

На входных данных — указатель на размер буфера RemoteAddress в байтах , предоставленного вызывающим объектом. На выходе — указатель на размер (в байтах) SOCKADDR для удаленного адреса, хранящегося в буфере RemoteAddress , заполненного системой после успешного завершения вызова.

[out] RemoteAddress

Указатель на структуру SOCKADDR , которая получает удаленный адрес подключения. Это те же сведения, которые будут возвращены функцией getpeername . Этот параметр может иметь значение NULL. В этом случае RemoteAddressLength игнорируется.

[in] timeout

Время (в миллисекундах) ожидания ответа от удаленного приложения перед прерыванием вызова.

Reserved

Зарезервировано для будущей реализации. Этот параметр должен иметь значение NULL.

Возвращаемое значение

Если соединение установлено, WSAConnectByName возвращает значение TRUE , а параметры LocalAddress и RemoteAddress заполняются, если эти буферы были предоставлены вызывающим объектом.

Если вызов завершается сбоем, возвращается значение FALSE . Затем можно вызвать WSAGetLastError для получения расширенных сведений об ошибке.

Код возврата Описание
WSAEHOSTUNREACH
Узел, переданный в качестве параметра nodename , был недостижим.
WSAEINVAL
В функцию передан недопустимый параметр. Параметр nodename или servicename не должен иметь значение NULL. Параметр Reserved должен иметь значение NULL.
WSAENOBUFS
Не удалось выделить достаточный объем памяти.
WSAENOTSOCK
В функцию передан недопустимый сокет. Параметр s не должен быть INVALID_SOCKET или NULL.
WSAETIMEDOUT
Ответ от удаленного приложения не был получен до превышения времени ожидания .

Комментарии

WSAConnectByName предоставляется для быстрого и прозрачного подключения к удаленным узлам на определенных портах. Он совместим с версиями IPv6 и IPv4.

Чтобы включить обмен данными по протоколам IPv6 и IPv4, используйте следующий метод:

  • Функция setsockopt должна вызываться в сокете, созданном для семейства адресов AF_INET6, чтобы отключить параметр сокета IPV6_V6ONLY перед вызовом WSAConnectByName. Это достигается путем вызова функции setsockopt в сокете с параметром уровня , равным IPPROTO_IPV6 (см . IPPROTO_IPV6 Параметры сокета), параметру optname присвоено значение IPV6_V6ONLY, а значение параметра optvalue равно нулю.

WSAConnectByName имеет ограничения: он работает только для сокетов, ориентированных на подключение, таких как сокеты типа SOCK_STREAM. Функция не поддерживает перекрывающееся или неблокирующее поведение. WSAConnectByName будет блокироваться, даже если сокет находится в неблокирующем режиме.

WSAConnectByName не поддерживает предоставленные пользователем данные во время установки подключения. Этот вызов также не поддерживает структуры FLOWSPEC. В случаях, когда эти функции необходимы, следует использовать WSAConnect .

В версиях, предшествующих Windows 10, если приложению необходимо выполнить привязку к определенному локальному адресу или порту, использовать WSAConnectByName нельзя, так как параметр сокета для WSAConnectByName должен быть несвязанным сокетом.

Это ограничение было удалено Windows 10.

Параметры RemoteAddress и LocalAddress указывают на структуру SOCKADDR , которая является универсальным типом данных. При вызове WSAConnectByName ожидается, что в этих параметрах будет передаваться тип адреса сокета, относящегося к используемому сетевому протоколу или семейству адресов. Поэтому для IPv4-адресов указатель на структуру sockaddr_in будет приведен к указателю на SOCKADDR в качестве параметров RemoteAddress и LocalAddress . Для IPv6-адресов указатель на структуру sockaddr_in6 будет приведен к указателю на SOCKADDR в качестве параметров RemoteAddress и LocalAddress .

Когда функция WSAConnectByName возвращает значение TRUE, сокеты будут в состоянии по умолчанию для подключенного сокета. Сокет не включает ранее заданные свойства или параметры до тех пор, пока в сокете не будет задано SO_UPDATE_CONNECT_CONTEXT. Используйте функцию setsockopt , чтобы задать параметр SO_UPDATE_CONNECT_CONTEXT.

Пример:

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

int iResult = 0;

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

Примечание При выполнении блокирующего вызова Winsock, например WSAConnectByName , с параметром timeout , равным NULL, Winsock может потребоваться дождаться сетевого события, прежде чем вызов может завершиться. В этой ситуации Winsock выполняет оповещенное ожидание, которое может быть прервано асинхронным вызовом процедуры (APC), запланированным в том же потоке. Выполнение другого блокирующего вызова Winsock внутри APC, который прервал текущий блокирующий вызов Winsock в том же потоке, приведет к неопределенному поведению, и клиенты Winsock никогда не должны пытаться его выполнять.
 
Windows Phone 8. Функция WSAConnectByNameW поддерживается для приложений Магазина Windows Phone на Windows Phone 8 и более поздних версий.

Windows 8.1 и Windows Server 2012 R2. Функция WSAConnectByNameW поддерживается для приложений Магазина Windows на Windows 8.1, Windows Server 2012 R2 и более поздних версий.

Примеры

Установите подключение с помощью 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;
    }
}

Примечание

Заголовок winsock2.h определяет WSAConnectByName в качестве псевдонима, который автоматически выбирает версию ANSI или Юникод этой функции на основе определения константы препроцессора ЮНИКОД. Использование псевдонима, не зависящий от кодирования, с кодом, который не является нейтральным для кодировки, может привести к несоответствиям, которые приводят к ошибкам компиляции или времени выполнения. Дополнительные сведения см. в разделе Соглашения для прототипов функций.

Требования

Требование Значение
Минимальная версия клиента Windows 8.1, Windows Vista [классические приложения | Приложения UWP]
Минимальная версия сервера Windows Server 2008 [классические приложения | Приложения UWP]
Целевая платформа Windows
Header winsock2.h
Библиотека Ws2_32.lib
DLL Ws2_32.dll

См. также раздел

Параметры сокета IPPROTO_IPV6

SOCKADDR

WSAConnect

WSAConnectByList

WSAGetLastError

getaddrinfo

getpeername

getsockname

setsockopt