共用方式為


WSAConnectByNameW 函式 (winsock2.h)

WSAConnectByName 函式會建立與指定主機和埠的連線。 提供此函式以允許在主機名和埠下快速連線到網路端點。

此函式同時支援 IPv4 和 IPv6 位址。

語法

BOOL WSAConnectByNameW(
  [in]      SOCKET          s,
  [in]      LPWSTR          nodename,
  [in]      LPWSTR          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」 是 Internet Engineering Task Force (IETF) 所定義之埠 80 的別名,作為 Web 伺服器用於 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 TRUELocalAddressRemoteAddress 參數,如果呼叫者提供這些緩衝區,則會填入這些緩衝區。

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

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

言論

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

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

  • setockopt 函式必須在為AF_INET6位址系列建立的套接字上呼叫,才能在呼叫 WSAConnectByName之前停用 IPV6_V6ONLY 套接字選項。 這可藉由呼叫套接字上的 setsockopt 函式,並將 層級 參數設定為 IPPROTO_IPV6 (請參閱 IPPROTO_IPV6 套接字選項)、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 8.1、Windows Server 2012 R2 及更新版本的 Windows 市集應用程式支援 WSAConnectByNameW 功能。

例子

使用 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 應用程式]
目標平臺 窗戶
標頭 winsock2.h
連結庫 Ws2_32.lib
DLL Ws2_32.dll

另請參閱

IPPROTO_IPV6 套接字選項

SOCKADDR

WSAConnect

WSAConnectByList

WSAGetLastError

getaddrinfo

getpeername

取得ockname

setockopt