Partager via


WSAConnectByList (Compact 7)

3/12/2014

This function establishes a connection to one endpoint out of a collection of possible endpoints that are represented by a set of destination addresses (host names and ports). This function takes all the destination addresses that are passed to it and all the local device's source addresses, and tries to connect by using all possible address combinations before giving up.

This function supports both IPv4 and IPv6 addresses.

Syntax

int  WSAConnectByName(
  SOCKET s,
    PSOCKET_ADDRESS_LIST SocketAddressList,
    LPDWORD LocalAddressLength,
    LPSOCKADDR LocalAddress,
    LPDWORD RemoteAddressLength,
    LPSOCKADDR RemoteAddress,
    const struct timeval* timeout,
    LPWSAOVERLAPPED Reserved
);

Parameters

  • s
    [in] Descriptor identifying an unconnected socket
  • SocketAddressList
    A pointer to a SOCKET_ADDRESS_LIST structure that represents the possible destination address and port pairs to connect to a peer. It is the application's responsibility to fill in the port number in the each SOCKET_ADDRESS structure in the SOCKET_ADDRESS_LIST.
  • LocalAddressLength
    On input, a pointer to the size, in bytes, of the LocalAddress buffer provided by the caller. On output, a pointer to the size, in bytes, of the SOCKADDR for the local address stored in the LocalAddress buffer filled in by the system upon successful completion of the call
  • LocalAddress
    A pointer to the SOCKADDR structure that receives the local address of the connection. The size of the parameter is exactly the size returned in LocalAddressLength. This is the same information that would be returned by the getsockname (Windows Sockets) function. This parameter can be NULL. In this case,, the LocalAddressLength parameter is ignored.
  • RemoteAddressLength
    On input, a pointer to the size, in bytes, of the RemoteAddress buffer provided by the caller. On output, a pointer to the size, in bytes, of the SOCKADDR for the remote address stored in RemoteAddress buffer filled-in by the system upon successful completion of the call.
  • RemoteAddress
    A pointer to the SOCKADDR structure that receives the remote address of the connection. This is the same information that would be returned by the getpeername (Windows Sockets) function. This parameter can be NULL. In this case, the RemoteAddressLength is ignored.
  • timeout
    The time, in milliseconds, to wait for a response from the remote application before aborting the call. This parameter can be NULL. In this case, WSAConnectByList will complete either after the connection is successfully established or after a connection was tried and failed on all possible local-remote address pairs.
  • Reserved
    Reserved; set to NULL.

Return Value

If a connection is established, WSAConnectByList returns TRUE and the LocalAddress and RemoteAddress parameters are filled in if these buffers were supplied by the caller.

If the call fails, FALSE is returned. WSAGetLastError can then be called to retrieve extended error information.

Return Code Description

WSAEHOSTUNREACH

The host passed as the nodename parameter was unreachable

WSAEINVAL

An invalid parameter was passed to the function. The nodename or the servicename parameter must not be NULL. The Reserved parameter must be NULL.

WSAENOBUFS

Sufficient memory could not be allocated

WSAENOTSOCK

An invalid socket was passed to the function. The s parameter must not be INVALID_SOCKET or NULL.

WSAETIMEDOUT

A response from the remote application was not received before the timeout parameter was exceeded.

Remarks

WSAConnectByList resembles the WSAConnectByName function. Instead of taking a single host name and service name (port), WSAConnectByList takes a list of addresses (host addresses and ports) and connects to one of the addresses. The WSAConnectByList function is designed to support peer-to-peer collaboration scenarios where an application has to connect to any available node out of a list of potential nodes. WSAConnectByList is compatible with both IPv6 and IPv4 versions.

In additional to iteratively trying to connect(), WSAConnectByList also considers Connection Manager policy.

The set of possible destinations, represented by a list of addresses, is provided by the caller. WSAConnectByList does more than try to connect to one of possibly many destination addresses. Specifically, the function takes all remote addresses passed in by the caller, all local addresses, and then tries a connection first using address pairs with the highest chance of success. Therefore, WSAConnectByList not only ensures that connection will be established if a connection is at all possible, but also minimizes the time to establish the connection.

The caller can specify the LocalAddress and RemoteAddress buffers and lengths to determine the local and remote addresses for which the connection was successfully established.

The timeout parameter lets the caller limit the time that is spent by the function in establishing a connection. Internally, WSAConnectByList performs multiple operations (connection attempts). In between each operation, the timeout parameter is checked to see whether the timeout is exceeded and, if so, the call is aborted. Notice that a specific operation (connect) will not be interrupted when the timeout is exceeded. So, the WSAConnectByList call can take longer to time out than the value specified in the timeout parameter.

WSAConnectByList has limitations: It works only for connection-oriented sockets, such as those of type SOCK_STREAM. The function does not support overlapped I/O or non-blocking behavior. WSAConnectByList will block even if the socket is in non-blocking mode. WSAConnectByList will try to connect (one-by-one) to the various addresses provided by the caller. Potentially, each of these connection tries may fail with a different error code. Because only a single error code can be returned, the value returned is the error code from the last connection attempt.

To enable both IPv6 and IPv4 addresses to be passed in the single address list accepted by the function, the following steps must be performed before calling the function:

  • The setsockopt (Windows Sockets) function must be called on a socket created for the AF_INET6 address family to disable the IPV6_V6ONLY socket option before calling WSAConnectByList. This is achieved by calling the setsockopt function on the socket with the level parameter set to IPPROTO_IPV6 (see IPPROTO_IPV6 Socket Options), the optname parameter set to IPV6_V6ONLY, and the optvalue parameter value set to zero.
  • Any IPv4 addresses must be represented in the IPv4-mapped IPv6 address format which enables an IPv6 only application to communicate with an IPv4 node. The IPv4-mapped IPv6 address format allows for the IPv4 address of an IPv4 node to be represented as an IPv6 address. The IPv4 address is encoded into the low-order 32 bits of the IPv6 address, and the high-order 96 bits hold the fixed prefix 0:0:0:0:0:FFFF. The IPv4-mapped IPv6 address format is specified in RFC 4291. For more information, see www.ietf.org/rfc/rfc4291.txt. The IN6ADDR_SETV4MAPPED macro in Mstcpip.h can be used to convert an IPv4 address to the required IPv4-mapped IPv6 address format.

The arrays of pointers that are passed in the SocketAddressList parameter point to an array of SOCKET_ADDRESS structures. These are a generic data type. The RemoteAddress and the LocalAddress parameters also point to SOCKADDR structures. When WSAConnectByList is called, it is expected that a socket address type that is specific to the network protocol or address family being used will actually be passed in these parameters. So for IPv4 addresses, a pointer to a sockaddr_in structure would be cast to a pointer to SOCKADDR when it is passed as a parameter. For IPv6 addresses, a pointer to a sockaddr_in6 structure would be cast to a pointer to SOCKADDR when it is passed as a parameter. The SocketAddressList parameter can contain pointers to a mixture of IPv4 and IPv6 addresses. So some SOCKET_ADDRESS pointers can be to sockaddr_in structures and other pointers can be to sockaddr_in6 structures. If it is expected that IPv6 addresses can be used, the RemoteAddress and LocalAddress parameters should point to sockaddr_in6 structures and be cast to SOCKADDR structures. The RemoteAddressLength and the LocalAddressLength parameters must represent the length of these larger structures.

Example Code

Establish a Connection Using WSAConnectByList:

Important

For readability, the following code example does not contain security checking or error handling. Do not use the following code in a production environment.

SOCKET
OpenAndConnect(SOCKET_ADDRESS_LIST *AddressList) 
{
    SOCKET ConnSocket;
    BOOL ipv6only = FALSE;
    SOCKADDR_STORAGE LocalAddr = {0}, RemoteAddr = {0};
    int ipv6only = 0;
    int iResult;
    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;
    }
}

See Also

Reference

Windows-Specific Extension Functions
SOCKET_ADDRESS
getsockname (Windows Sockets)
getpeername (Windows Sockets)
WSAGetLastError
WSAConnect
WSAConnectByName
setsockopt (Windows Sockets)
IPPROTO_IPV6
sockaddr_in
sockaddr_in6