connect 函数 (winsock2.h)

connect 函数与指定的套接字建立连接。

语法

int WSAAPI connect(
  [in] SOCKET         s,
  [in] const sockaddr *name,
  [in] int            namelen
);

参数

[in] s

标识未连接的套接字的描述符。

[in] name

指向应建立连接的 sockaddr 结构的指针。

[in] namelen

name 参数指向的 sockaddr 结构的长度(以字节为单位)。

返回值

如果未发生错误, 则连接 返回零。 否则,它将返回SOCKET_ERROR,并且可以通过调用 WSAGetLastError 来检索特定的错误代码。

在阻塞套接字上,返回值指示连接尝试成功或失败。

使用非阻止套接字时,无法立即完成连接尝试。 在这种情况下, 连接 将返回SOCKET_ERROR, WSAGetLastError 将返回 WSAEWOULDBLOCK。 在这种情况下,有三种可能的方案:

  • 使用 select 函数通过检查套接字是否可写来确定连接请求的完成情况。
  • 如果应用程序使用 WSAAsyncSelect 来指示对连接事件感兴趣,则应用程序将收到FD_CONNECT通知,指示 连接 操作已完成 (成功或未) 。
  • 如果应用程序使用 WSAEventSelect 来指示对连接事件的兴趣,则将向关联的事件对象发出信号,指示 连接 操作已完成 (成功或未) 。

在非阻止套接字上完成连接尝试之前,在连接成功完成时,在同一套接字上进行 连接 的所有后续调用都将失败并出现错误代码 WSAEALREADYWSAEISCONN 。 由于 Windows 套接字规范版本 1.1 中的多义性,在连接已挂起时从 连接 返回的错误代码可能因实现而异。 因此,不建议应用程序使用多个调用进行连接以检测连接完成情况。 如果他们这样做,则必须准备好处理 WSAEINVALWSAEWOULDBLOCK 错误值的方式与处理 WSAEALREADY 的方式相同,以确保可靠的操作。

如果返回的错误代码指示连接尝试失败 (即 WSAECONNREFUSEDWSAENETUNREACHWSAETIMEDOUT) 应用程序可以为同一套接字再次调用 connect

错误代码 含义
WSANOTINITIALISED
在使用此函数之前,必须成功调用 WSAStartup
WSAENETDOWN
网络子系统失败。
WSAEADDRINUSE
套接字的本地地址已在使用中,并且未将套接字标记为允许使用 SO_REUSEADDR 重用地址。 此错误通常在执行绑定时发生,但如果绑定是本地 IP 地址的通配符地址 (INADDR_ANYin6addr_any) ,则可能会延迟到连接功能。 特定地址需要由 connect 函数隐式绑定。
WSAEINTR
阻止的 Windows 套接字 1.1 调用已通过 WSACancelBlockingCall 取消。
WSAEINPROGRESS
阻止 Windows Sockets 1.1 调用正在进行,或者服务提供程序仍在处理回调函数。
WSAEALREADY
正在指定的套接字上进行非阻止 连接 调用。
注意 为了保持向后兼容性,此错误以 WSAEINVAL 的形式报告给链接到 Winsock.dll 或 Wsock32.dll 的 Windows 套接字 1.1 应用程序。
 
WSAEADDRNOTAVAIL
远程地址不是有效的地址 (,例如 INADDR_ANYin6addr_any) 。
WSAEAFNOSUPPORT
指定系列中的地址无法与此套接字一起使用。
WSAECONNREFUSED
尝试连接被强制性拒绝。
WSAEFAULT
名称指向的 sockaddr 结构包含关联的地址系列地址格式不正确,或者 namelen 参数太小。 如果 name 参数所指向的长度在 namelen 参数中指定的 sockaddr 结构不在用户地址空间的有效部分,则也会返回此错误。
WSAEINVAL
参数 s 是侦听套接字。
WSAEISCONN
仅) 面向连接的套接字 (已连接套接字。
WSAENETUNREACH
此时不可以从此主机访问该网络。
WSAEHOSTUNREACH
套接字操作尝试访问无法访问的主机。
WSAENOBUFS
注意 没有可用的缓冲区空间。 无法连接套接字。
 
WSAENOTSOCK
s 参数中指定的描述符不是套接字。
WSAETIMEDOUT
尝试连接超时,但未建立连接。
WSAEWOULDBLOCK
:套接字标记为非阻止,无法立即完成连接。
WSAEACCES
尝试将数据报套接字连接到广播地址失败,因为未启用 setsockopt 选项SO_BROADCAST。

备注

connect 函数用于创建到指定目标的连接。 如果套接字 绑定,则系统会将唯一值分配给本地关联,并将套接字标记为绑定。

对于面向连接的套接字 (例如,SOCK_STREAM) 类型,将使用 名称 (套接字命名空间中的地址发起到外部主机的活动连接;有关详细说明,请参阅 bindsockaddr) 。

注意 如果打开套接字,进行 setsockopt 调用,然后发出 sendto 调用,Windows 套接字将执行隐式 绑定 函数调用。

 

套接字调用成功完成后,套接字已准备好发送和接收数据。 如果 name 参数指定的结构的地址成员用零填充, 则连接 将返回错误 WSAEADDRNOTAVAIL。 重新连接活动连接的任何尝试都将失败,错误代码为 WSAEISCONN

对于面向连接的非阻塞套接字,通常无法立即完成连接。 在这种情况下,此函数返回错误 WSAEWOULDBLOCK。 但是,该操作继续进行。

当成功或失败结果已知时,可能会以两种方式之一进行报告,具体取决于客户端注册通知的方式。

  • 如果客户端使用 select 函数,则会在 writefds 集中报告成功,在 exceptfds 集中报告失败。
  • 如果客户端使用函数 WSAAsyncSelectWSAEventSelect,则会使用 FD_CONNECT 通知,并且与FD_CONNECT关联的错误代码指示成功或失败的特定原因。

如果未立即完成连接,客户端应等待连接完成,然后尝试使用 setsockopt 设置套接字选项。 不支持在连接正在进行时调用 setsockopt。

对于无连接套接字 (例如,SOCK_DGRAM) 类型, 连接 执行的操作只是为了建立可用于后续 发送/ WSASendrecv/ WSARecv 调用的默认目标地址。 从指定的目标地址以外的地址接收的任何数据报将被丢弃。 如果 name 指定的结构的地址成员用零填充,则套接字将断开连接。 然后,默认远程地址将不确定,因此 send/ WSASendrecv/ WSARecv 调用将返回错误代码 WSAENOTCONN。 但是, sendto/ WSASendTorecvfrom/ WSARecvFrom 仍可使用。 只需再次调用 连接 即可更改默认目标,即使套接字已连接也是如此。 如果 名称 与上一个 连接不同,则放弃排队接收的任何数据报。

对于无连接套接字, 名称 可以指示任何有效的地址,包括广播地址。 但是,若要连接到广播地址,套接字必须使用 setsockopt 来启用SO_BROADCAST选项。 否则, 连接 将失败,错误代码 为 WSAEACCES

当套接字之间的连接断开时,应放弃已连接的套接字,并创建新的套接字。 当在连接的套接字上出现问题时,应用程序必须放弃套接字并再次创建套接字,以便返回到稳定点。

注意 发出阻止的 Winsock 调用(如 连接)时,Winsock 可能需要等待网络事件,才能完成调用。 在这种情况下,Winsock 执行可发出警报的等待, (在同一线程上计划的 APC) 异步过程调用可能会中断该等待。 在 APC 内发出另一个阻止 Winsock 调用,该调用中断了同一线程上正在进行的阻止 Winsock 调用将导致未定义的行为,并且 Winsock 客户端绝不能尝试。
 

示例代码

以下示例演示如何使用 connect 函数。
#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")

int wmain()
{
    //----------------------
    // Initialize Winsock
    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup function failed with error: %d\n", iResult);
        return 1;
    }
    //----------------------
    // Create a SOCKET for connecting to server
    SOCKET ConnectSocket;
    ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ConnectSocket == INVALID_SOCKET) {
        wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port of the server to be connected to.
    sockaddr_in clientService;
    clientService.sin_family = AF_INET;
    clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
    clientService.sin_port = htons(27015);

    //----------------------
    // Connect to server.
    iResult = connect(ConnectSocket, (SOCKADDR *) & clientService, sizeof (clientService));
    if (iResult == SOCKET_ERROR) {
        wprintf(L"connect function failed with error: %ld\n", WSAGetLastError());
        iResult = closesocket(ConnectSocket);
        if (iResult == SOCKET_ERROR)
            wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    wprintf(L"Connected to server.\n");

    iResult = closesocket(ConnectSocket);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    WSACleanup();
    return 0;
}


有关使用 connect 函数的另一个示例,请参阅 入门 With Winsock

IrDA 套接字说明

  • 必须显式包含 Af_irda.h 头文件。
  • 如果在媒体访问级别检测到现有的 IrDA 连接,则返回 WSAENETDOWN
  • 如果存在与具有不同地址的设备的活动连接,则返回 WSAEADDRINUSE
  • 如果套接字已连接或独占/多路复用模式更改失败,则返回 WSAEISCONN
  • 如果套接字以前绑定到本地服务名称以使用 绑定接受传入连接,则返回 WSAEINVAL 。 请注意,绑定套接字后,它不能用于建立出站连接。

IrDA 使用表单sockaddr_irda地址实现 connect 函数。 通常,客户端应用程序将使用套接字功能创建一个套接字,使用“IRLMP_ENUMDEVICES套接字”选项扫描 IrDA 设备的邻近区域,从返回的列表中选择设备,形成地址,然后调用 connect。 阻止语义和非阻止语义之间没有区别。

要求

   
最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用]
最低受支持的服务器 Windows Server 2003 [桌面应用 | UWP 应用]
目标平台 Windows
标头 winsock2.h
Library Ws2_32.lib
DLL Ws2_32.dll

另请参阅

WSAAsyncSelect

WSAConnect

ConnectEx

Winsock 函数

Winsock 参考

accept

bind

getsockname

select

sockaddr

socket