WSAConnectByList 함수(winsock2.h)

WSAConnectByList 함수는 대상 주소 집합(호스트 이름 및 포트)으로 표현되는 가능한 엔드포인트 컬렉션 중 하나에 대한 연결을 설정합니다. 이 함수는 전달된 모든 대상 주소와 로컬 컴퓨터의 모든 원본 주소를 사용하고 포기하기 전에 가능한 모든 주소 조합을 사용하여 연결을 시도합니다.

이 함수는 IPv4 및 IPv6 주소를 모두 지원합니다.

구문

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
);

매개 변수

[in] s

바인딩되지 않은 연결되지 않은 소켓을 식별하는 설명자입니다. 연결을 설정하기 위한 다른 Winsock 호출(예: WSAConnect)와 달리 WSAConnectByList 함수에는 언바운드 소켓이 필요합니다.

[in] SocketAddress

피어에 연결할 수 있는 대상 주소 및 포트 쌍을 나타내는 SOCKET_ADDRESS_LIST 구조체에 대한 포인터입니다. SOCKET_ADDRESS_LIST 각 SOCKET_ADDRESS 구조에서 포트 번호를 채우는 것은 애플리케이션의 책임입니다.

[in, out] LocalAddressLength

입력 시 호출자가 제공하는 LocalAddress 버퍼의 크기(바이트)에 대한 포인터입니다. 출력 시 호출이 성공적으로 완료되면 시스템에서 입력한 LocalAddress 버퍼에 저장된 로컬 주소에 대한 SOCKADDR의 크기(바이트)에 대한 포인터입니다.

[out] LocalAddress

연결의 로컬 주소를 수신하는 SOCKADDR 구조체에 대한 포인터입니다. 매개 변수의 크기는 LocalAddressLength에서 반환된 크기입니다. 이 정보는 getsockname 함수에서 반환되는 것과 동일한 정보입니다. 이 매개 변수는 NULL일 수 있으며, 이 경우 LocalAddressLength 매개 변수는 무시됩니다.

[in, out] RemoteAddressLength

입력 시 호출자가 제공하는 RemoteAddress 버퍼의 크기(바이트)에 대한 포인터입니다. 출력 시 호출이 성공적으로 완료되면 시스템에서 RemoteAddress 버퍼에 저장된 원격 주소에 대한 SOCKADDR 크기(바이트)에 대한 포인터입니다.

[out] RemoteAddress

연결의 원격 주소를 수신하는 SOCKADDR 구조체에 대한 포인터입니다. getpeername 함수에서 반환하는 것과 동일한 정보입니다. 이 매개 변수는 NULL일 수 있으며, 이 경우 RemoteAddressLength 는 무시됩니다.

[in] timeout

호출을 중단하기 전에 원격 애플리케이션의 응답을 기다리는 시간(밀리초)입니다. 이 매개 변수는 연결이 성공적으로 설정된 후 또는 가능한 모든 로컬 원격 주소 쌍에서 연결을 시도하고 실패한 후 WSAConnectByList가 완료되는 경우 NULL일 수 있습니다.

[in] Reserved

향후 구현을 위해 예약됩니다. 이 매개 변수는 NULL로 설정해야 합니다.

반환 값

연결이 설정되면 WSAConnectByListTRUE 를 반환하고, 호출자가 이러한 버퍼를 제공한 경우 LocalAddressRemoteAddress 매개 변수가 채워집니다.

호출이 실패하면 FALSE 가 반환됩니다. 그런 다음 WSAGetLastError를 호출하여 확장된 오류 정보를 가져올 수 있습니다.

반환 코드 설명
WSAEHOSTUNREACH
nodename 매개 변수로 전달된 호스트에 연결할 수 없습니다.
WSAEINVAL
잘못된 매개 변수가 함수에 전달되었습니다. Reserved 매개 변수는 NULL이어야 합니다.
WSAENOBUFS
충분한 메모리를 할당할 수 없습니다.
WSAENOTSOCK
잘못된 소켓이 함수에 전달되었습니다. s 매개 변수는 INVALID_SOCKET 또는 NULL이 아니어야 합니다.
WSAETIMEDOUT
시간 제한 매개 변수를 초과하기 전에 원격 애플리케이션의 응답을 받지 못했습니다.

설명

WSAConnectByListWSAConnectByName 함수와 유사합니다. WSAConnectByList는 단일 호스트 이름 및 서비스 이름(포트)을 사용하는 대신 주소 목록(호스트 주소 및 포트)을 가져와 주소 중 하나에 연결합니다. WSAConnectByList 함수는 애플리케이션이 잠재적 노드 목록에서 사용 가능한 노드에 연결해야 하는 피어 투 피어 협업 시나리오를 지원하도록 설계되었습니다. WSAConnectByList 는 IPv6 및 IPv4 버전 모두와 호환됩니다.

주소 목록으로 표시되는 가능한 대상 집합은 호출자가 제공합니다. WSAConnectByList 는 여러 대상 주소 중 하나에 단순히 연결을 시도하는 것 이상을 수행합니다. 특히 함수는 호출자가 전달한 모든 원격 주소, 모든 로컬 주소를 사용한 다음 성공 가능성이 가장 높은 주소 쌍을 사용하여 먼저 연결을 시도합니다. 따라서 WSAConnectByList 는 연결이 가능한 경우 연결이 설정되도록 할 뿐만 아니라 연결 설정 시간을 최소화합니다.

호출자는 LocalAddressRemoteAddress 버퍼와 길이를 지정하여 연결이 성공적으로 설정된 로컬 및 원격 주소를 확인할 수 있습니다.

시간 제한 매개 변수를 사용하면 호출자가 함수가 연결을 설정하는 데 소요된 시간을 제한할 수 있습니다. 내부적으로 WSAConnectByList 는 여러 작업(연결 시도)을 수행합니다. 각 작업 간에 시간 제한 매개 변수를 확인하여 시간 제한이 초과되었는지 확인하고, 초과된 경우 호출이 중단됩니다. 시간 제한을 초과하면 개별 작업(연결)이 중단되지 않으므로 WSAConnectByList 호출은 시간 제한 매개 변수에 지정된 값보다 시간이 오래 걸릴 수 있습니다.

WSAConnectByList 에는 제한 사항이 있습니다. SOCK_STREAM 형식의 소켓과 같은 연결 지향 소켓에서만 작동합니다. 함수는 겹치는 I/O 또는 비블로킹 동작을 지원하지 않습니다. 소켓이 비차단 모드인 경우에도 WSAConnectByList가 차단됩니다. WSAConnectByList 는 호출자가 제공하는 다양한 주소에 연결(일대일)을 시도합니다. 잠재적으로 이러한 각 연결 시도는 다른 오류 코드로 실패할 수 있습니다. 단일 오류 코드만 반환할 수 있으므로 반환되는 값은 마지막 연결 시도의 오류 코드입니다.

함수에서 허용하는 단일 주소 목록에 IPv6 및 IPv4 주소를 모두 전달할 수 있도록 하려면 함수를 호출하기 전에 다음 단계를 수행해야 합니다.

  • WSAConnectByList를 호출하기 전에 AF_INET6 주소 패밀리에 대해 만든 소켓에서 setsockopt 함수를 호출하여 IPV6_V6ONLY 소켓 옵션을 사용하지 않도록 설정해야 합니다. 이 작업은 수준 매개 변수가 IPPROTO_IPV6(IPPROTO_IPV6 Socket 옵션 참조), optname 매개 변수가 IPV6_V6ONLY 설정되고 optvalue 매개 변수 값이 0으로 설정된 소켓에서 setsockopt 함수를 호출하여 수행됩니다.
  • 모든 IPv4 주소는 IPv4 노드와 통신 하는 IPv6만 애플리케이션을 사용 하도록 설정 하는 IPv4 매핑된 IPv6 주소 형식으로 표현 되어야 합니다. IPv4 매핑된 IPv6 주소 형식을 사용하면 IPv4 노드의 IPv4 주소를 IPv6 주소로 나타낼 수 있습니다. IPv4 주소는 IPv6 주소의 하위 32비트로 인코딩되고, 상위 96비트에서는 고정 접두사 0:0:0:0:0:FFFF를 보유합니다. IPv4 매핑된 IPv6 주소 형식은 RFC 4291에 지정됩니다. 자세한 내용은 www.ietf.org/rfc/rfc4291.txt참조하세요. Mstcpip.h의 IN6ADDR_SETV4MAPPED 매크로를 사용하여 IPv4 주소를 필요한 IPv4 매핑 IPv6 주소 형식으로 변환할 수 있습니다.

SocketAddressList 매개 변수에 전달된 포인터 배열은 제네릭 데이터 형식인 SOCKET_ADDRESS 구조의 배열을 가리킵니다. RemoteAddressLocalAddress 매개 변수도 SOCKADDR 구조를 가리킵니다. WSAConnectByList가 호출되면 사용되는 네트워크 프로토콜 또는 주소 패밀리와 관련된 소켓 주소 유형이 실제로 이러한 매개 변수에 전달될 것으로 예상됩니다. 따라서 IPv4 주소의 경우 매개 변수로 전달될 때 sockaddr_in 구조체에 대한 포인터가 SOCKADDR 에 대한 포인터로 캐스팅됩니다. IPv6 주소의 경우 매개 변수로 전달될 때 sockaddr_in6 구조체에 대한 포인터가 SOCKADDR 에 대한 포인터로 캐스팅됩니다. SocketAddressList 매개 변수는 IPv4 및 IPv6 주소의 혼합에 대한 포인터를 포함할 수 있습니다. 따라서 일부 SOCKET_ADDRESS 포인터 는 sockaddr_in 구조 체일 수 있고 다른 SOCKET_ADDRESS 구조체를 sockaddr_in6 수 있습니다. IPv6 주소를 사용할 수 있을 것으로 예상되는 경우 RemoteAddressLocalAddress 매개 변수는 sockaddr_in6 구조를 가리키고 SOCKADDR 구조체로 캐스팅되어야 합니다. RemoteAddressLengthLocalAddressLength 매개 변수는 이러한 더 큰 구조체의 길이를 나타내야 합니다.

WSAConnectByList 함수가 TRUE를 반환하면 소켓 연결된 소켓의 기본 상태입니다. 소켓 s 는 소켓에서 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 );

참고시간 제한 매개 변수가 NULL로 설정된 WSAConnectByList와 같은 차단 Winsock 호출을 실행하는 경우 Winsock은 호출이 완료되기 전에 네트워크 이벤트를 기다려야 할 수 있습니다. Winsock은 이 상황에서 경고 가능한 대기를 수행합니다. 이 대기는 동일한 스레드에서 예약된 APC(비동기 프로시저 호출)에 의해 중단될 수 있습니다. 동일한 스레드에서 지속적인 차단 Winsock 호출을 중단한 APC 내에서 다른 차단 Winsock 호출을 실행하면 정의되지 않은 동작이 발생하며 Winsock 클라이언트에서 시도해서는 안 됩니다.
 
Windows Phone 8: 이 함수는 Windows Phone 8 이상에서 Windows Phone 스토어 앱에서 지원됩니다.

Windows 8.1Windows Server 2012 R2: 이 함수는 Windows 8.1, Windows Server 2012 R2 이상의 Windows 스토어 앱에서 지원됩니다.

예제

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;
    }
}

요구 사항

   
지원되는 최소 클라이언트 Windows 8.1, Windows Vista [데스크톱 앱 | UWP 앱]
지원되는 최소 서버 Windows Server 2003 [데스크톱 앱 | UWP 앱]
대상 플랫폼 Windows
헤더 winsock2.h
라이브러리 Ws2_32.lib
DLL Ws2_32.dll

추가 정보

IPPROTO_IPV6 소켓 옵션

SOCKADDR

SOCKET_ADDRESS

SOCKET_ADDRESS_LIST

WSAConnect

WSAConnectByName

WSAGetLastError

getaddrinfo

getpeername

getsockname

setsockopt