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 終止的字串,其中包含要針對 IPv4 或 IPv6 連線之主機的名稱或主機的 IP 位址。

[in] servicename

NULL 終止的字串,其中包含要連線至 IPv4 或 IPv6 之主機的服務名稱或目的地埠。

服務名稱是埠號碼的字串別名。 例如,「HTTP」 是因特網工程工作組 (IETF) 所定義之埠 80 的別名,做為 Web 伺服器用於 HTTP 通訊協定的預設埠。 未指定埠號碼時 ,servicename 參數的可能值會列在下列檔案中:

%WINDIR%\system32\drivers\etc\services

[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

在中止呼叫之前,等候遠端應用程式回應的時間,以毫秒為單位。

Reserved

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

傳回值

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

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

傳回碼 Description
WSAEHOSTUNREACH
無法連線到傳遞為 nodename 參數的主機。
WSAEINVAL
無效的參數已傳遞至 函式。 nodenameservicename 參數不得為 NULLReserved 參數必須是 NULL
WSAENOBUFS
無法配置足夠的記憶體。
WSAENOTSOCK
傳遞至函式的套接字無效。 s 參數不得INVALID_SOCKETNULL
WSAETIMEDOUT
超過 時參數之前,未收到來自遠端應用程式的回應。

備註

提供 WSAConnectByName ,以便快速且透明地連線到特定埠上的遠端主機。 它與 IPv6 和 IPv4 版本相容。

若要啟用 IPv6 和 IPv4 通訊,請使用下列方法:

  • 在為AF_INET6位址系列建立的套接字上呼叫 setsockopt 函式,才能在呼叫 WSAConnectByName 之前停用 IPV6_V6ONLY 套接字選項。 這可藉由呼叫套接字上的 setsockopt 函式,並將 level 參數設定為 IPPROTO_IPV6 ( 請參閱 IPPROTO_IPV6 Socket Options) 、 optname 參數設定為 IPV6_V6ONLY,以及 optvalue 參數值設定為零 。

WSAConnectByName 有限制:它只適用於連線導向套接字,例如類型為 SOCK_STREAM 的套接字。 函式不支援重疊的 I/O 或非封鎖行為。 即使套接字處於非封鎖模式,WSAConnectByName 也會封鎖。

WSAConnectByName 在建立連線期間不支援使用者提供的數據。 此呼叫不支援 FLOWSPEC 結構。 如果需要這些功能,則必須改用 WSAConnect

在 Windows 10 之前的版本中,如果應用程式需要系結至特定的本機位址或埠,則無法使用 WSAConnectByName,因為 WSAConnectByName套接字參數必須是未繫結的套接字。

此限制已移除 Windows 10。

RemoteAddressLocalAddress 參數會指向 SOCKADDR 結構,這是泛型數據類型。 呼叫 WSAConnectByName 時,預期會實際傳入這些參數中所使用的網路協定或位址系列特定的套接字地址類型。 因此,針對 IPv4 位址, sockaddr_in 結構的指標會轉換成 SOCKADDR 的指標作為 RemoteAddressLocalAddress 參數。 針對 IPv6 位址, sockaddr_in6 結構的指標會轉換成 SOCKADDR 的指標作為 RemoteAddressLocalAddress 參數。

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

Windows 8.1Windows Server 2012 R2:Windows 市集應用程式支援 WSAConnectByNameW 函式,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 標頭會根據 UNICODE 預處理器常數的定義,將 WSAConnectByName 定義為別名,自動選取此函式的 ANSI 或 Unicode 版本。 混合使用編碼中性別名與非編碼中性的程序代碼,可能會導致編譯或運行時間錯誤不符。 如需詳細資訊,請參閱 函式原型的慣例

規格需求

需求
最低支援的用戶端 Windows 8.1、Windows Vista [傳統型應用程式 |UWP 應用程式]
最低支援的伺服器 Windows Server 2008 [傳統型應用程式 |UWP 應用程式]
目標平台 Windows
標頭 winsock2.h
程式庫 Ws2_32.lib
Dll Ws2_32.dll

另請參閱

IPPROTO_IPV6套接字選項

SOCKADDR

WSAConnect

WSAConnectByList

WSAGetLastError

getaddrinfo

getpeername

getsockname

setsockopt