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

在中止呼叫之前,等候遠端應用程式回應的時間,以毫秒為單位。 此參數可以是 Null ,在此情況下 ,WSAConnectByList 會在連線成功建立或嘗試連線之後完成,並在所有可能的本機遠端位址配對上失敗。

[in] Reserved

保留給未來的實作。 此參數必須設定為 Null

傳回值

如果已建立連線,如果呼叫端提供這些緩衝區, WSAConnectByList 會傳回 TRUELocalAddressRemoteAddress 參數。

如果呼叫失敗,則會傳回 FALSE 。 接著可以呼叫WSAGetLastError以取得擴充的錯誤資訊。

傳回碼 描述
WSAEHOSTUNREACH
無法連線到傳遞為 nodename 參數的主機。
WSAEINVAL
不正確參數已傳遞至 函式。 Reserved參數必須是Null
WSAENOBUFS
無法配置足夠的記憶體。
WSAENOTSOCK
傳遞至函式的通訊端無效。 s參數不得INVALID_SOCKETNull
WSAETIMEDOUT
超過 時參數之前,未收到來自遠端應用程式的回應。

備註

WSAConnectByList 類似于 WSAConnectByName 函式。 WSAConnectByList不會 (埠) 採用單一主機名稱和服務名稱,而是 (主機位址和埠清單) 並聯機到其中一個位址。 WSAConnectByList函式的設計目的是支援點對點共同作業案例,其中應用程式必須連線到任何可用節點,而無法從潛在節點清單中連線。 WSAConnectByList 與 IPv6 和 IPv4 版本相容。

呼叫端會提供一組可能的目的地,以地址清單表示。 WSAConnectByList 不只是嘗試連線到其中一個可能許多目的地位址。 具體而言,函式會接受呼叫端、所有本機位址傳入的所有遠端位址,然後嘗試先使用位址組來嘗試連線,且成功的機會最高。 因此, WSAConnectByList 不僅可確保連線完全可行時,也會確保建立連線的時間降到最低。

呼叫端可以指定 LocalAddressRemoteAddress 緩衝區和長度,以判斷成功建立連線的本機和遠端位址。

timeout參數可讓呼叫端限制函式在建立連接時所花費的時間。 在內部, WSAConnectByList 會在) (連線嘗試執行多項作業。 在每個作業之間,會檢查 timeout 參數,以查看逾 時是否已超過 ,如果是,則會中止呼叫。 請注意, (連線) 個別作業不會在超過 時後中斷,因此 WSAConnectByList 呼叫可能需要比 逾時 參數中指定的值更長的時間。

WSAConnectByList 有限制:它只適用于連線導向通訊端,例如類型為 SOCK_STREAM 的通訊端。 函式不支援重迭的 I/O 或非封鎖行為。 即使通訊端處於非封鎖模式,WSAConnectByList也會封鎖。 WSAConnectByList 會嘗試 (一對一) 連接到呼叫端所提供的各種位址。 這些連線嘗試可能會失敗,並出現不同的錯誤碼。 因為只能傳回單一錯誤碼,所以傳回的值是上一次連線嘗試的錯誤碼。

若要讓 IPv6 和 IPv4 位址都傳遞至函式所接受的單一地址清單中,必須先執行下列步驟,才能呼叫 函式:

  • 在為AF_INET6位址系列建立的通訊端上呼叫setsockopt函式,才能在呼叫WSAConnectByList之前停用IPV6_V6ONLY通訊端選項。 這可藉由呼叫通訊端上的 setsockopt 函式,並將 level 參數設定為 IPPROTO_IPV6 ( 請參閱 IPPROTO_IPV6 Socket Options) 、 optname 參數設定為 IPV6_V6ONLY,以及 optvalue 參數值設定為零 。
  • 任何 IPv4 位址都必須以 IPv4 對應 IPv6 位址格式來表示,這可讓 IPv6 僅應用程式與 IPv4 節點通訊。 IPv4 對應 IPv6 位址格式可讓 IPv4 節點的 IPv4 位址表示為 IPv6 位址。 IPv4 位址會編碼為 IPv6 位址的低序 32 位,而高階 96 位則保留固定前置詞 0:0:0:0:FFFF。 RFC 4291 中指定了 IPv4 對應 IPv6 位址格式。 如需詳細資訊,請參閱 www.ietf.org/rfc/rfc4291.txtMstcpip.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 結構,而其他指標則是 sockaddr_in6 結構。 如果預期可以使用 IPv6 位址,則 RemoteAddress 和 LocalAddress參數應該指向sockaddr_in6結構,並轉換成SOCKADDR結構。 RemoteAddressLengthLocalAddressLength參數必須代表這些較大結構的長度。

WSAConnectByList 函式傳回 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 呼叫時,例如 WSAConnectByList ,且 逾時 參數設定為 Null時,Winsock 可能需要等候網路事件,才能完成呼叫。 在此情況下,Winsock 會執行可警示的等候,而非同步程序呼叫 (APC) 排程在相同執行緒上可能會中斷。 在 APC 內發出另一個封鎖 Winsock 呼叫,中斷相同執行緒上持續封鎖 Winsock 呼叫會導致未定義的行為,而且永遠不會由 Winsock 用戶端嘗試。
 
Windows Phone 8:Windows Phone Windows Phone 8 和更新版本上的市集應用程式支援此函式。

Windows 8.1Windows Server 2012 R2:Windows 市集應用程式在 Windows 8.1、Windows Server 2012 R2 及更新版本上支援此功能。

範例

使用 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