LPFN_CONNECTEX回调函数 (mswsock.h)

ConnectEx 函数与指定的套接字建立连接,并可以选择在建立连接后发送数据。 仅在面向连接的套接字上支持 ConnectEx 函数。

注意 此函数是 Windows 套接字规范中特定于 Microsoft 的扩展。

 

语法

LPFN_CONNECTEX LpfnConnectex;

BOOL LpfnConnectex(
  [in]           SOCKET s,
  [in]           const sockaddr *name,
  [in]           int namelen,
  [in, optional] PVOID lpSendBuffer,
  [in]           DWORD dwSendDataLength,
  [out]          LPDWORD lpdwBytesSent,
  [in]           LPOVERLAPPED lpOverlapped
)
{...}

参数

[in] s

标识未连接的以前绑定的套接字的描述符。 有关更多信息,请参见备注。

[in] name

指向 的指针
sockaddr 结构,指定要连接到的地址。 对于 IPv4,sockaddr 包含地址系列、目标 IPv4 地址和目标端口的AF_INET 对于 IPv6,sockaddr 结构包含地址系列、目标 IPv6 地址、目标端口 的AF_INET6 ,并且可能包含其他 IPv6 流和范围 ID 信息。

[in] namelen

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

[in, optional] lpSendBuffer

指向建立连接后要传输的缓冲区的指针。 此参数是可选的。 如果在调用 ConnectEx之前启用了 TCP_FASTOPEN 选项,则在建立连接期间可能会发送其中一些数据。

[in] dwSendDataLength

lpSendBuffer 参数指向的数据的长度(以字节为单位)。 当 lpSendBuffer 参数为 NULL 时,将忽略此参数。

[out] lpdwBytesSent

成功返回后,此参数指向 一个 DWORD 值,该值指示建立连接后发送的字节数。 发送的字节来自 lpSendBuffer 参数指向的缓冲区。 当 lpSendBuffer 参数为 NULL 时,将忽略此参数。

[in] lpOverlapped

用于处理请求的 OVERLAPPED 结构。 必须指定 lpOverlapped 参数,并且不能为 NULL

返回值

成功后, ConnectEx 函数返回 TRUE。 失败时,函数返回 FALSE。 使用 WSAGetLastError 函数获取扩展错误信息。 如果对 WSAGetLastError 函数的调用返回 ERROR_IO_PENDING,则表示操作已成功启动并正在进行中。 在这种情况下,当重叠的操作完成时,调用可能仍然失败。

如果返回的错误代码是 WSAECONNREFUSEDWSAENETUNREACHWSAETIMEDOUT,则应用程序可以调用 ConnectExWSAConnect 或在同一套接字上再次 连接

错误代码 说明
WSANOTINITIALIZED
在使用 ConnectEx 之前,必须成功调用 WSAStartup 函数。
WSAENETDOWN
网络子系统发生故障。
WSAEADDRINUSE
套接字的本地地址已在使用中,并且未将套接字标记为允许使用 SO_REUSEADDR 重用地址。 此错误通常在绑定操作期间发生,但如果调用绑定函数时使用通配符地址 (INADDR_ANY或in6addr_any为本地 IP 地址指定) ,则错误可能会延迟到 ConnectEx 函数调用。 特定 IP 地址需要由 ConnectEx 函数隐式绑定。
WSAEALREADY
在指定的套接字上正在进行非阻止 连接WSAConnectConnectEx 函数调用。
WSAEADDRNOTAVAIL
远程地址不是有效的地址,例如ADDR_ANY (ConnectEx 函数仅支持面向连接的套接字) 。
WSAEAFNOSUPPORT
指定系列中的地址无法与此套接字一起使用。
WSAECONNREFUSED
:连接尝试被拒绝。
WSAEFAULT
namelpSendBufferlpOverlapped 参数不是用户地址空间的有效部分,或者 namelen 太小。
WSAEINVAL
参数 s 是未绑定或侦听套接字。
WSAEISCONN
:套接字已连接。
WSAENETUNREACH
此时不可以从此主机访问该网络。
WSAEHOSTUNREACH
套接字操作尝试访问无法访问的主机。
WSAENOBUFS
没有可用的缓冲区空间;无法连接套接字。
WSAENOTSOCK
:描述符不是套接字。
WSAETIMEDOUT
:连接尝试超时,没有建立连接。

注解

ConnectEx 函数将多个套接字函数合并到单个 API/内核转换中。 对 ConnectEx 函数的调用成功完成时,将执行以下操作:

  • 建立新连接。
  • 建立连接后,会发送可选的数据块。

对于面向 Windows Vista 及更高版本的应用程序,请考虑使用 WSAConnectByListWSAConnectByName 函数,以大大简化客户端应用程序设计。

ConnectEx 函数只能与面向连接的套接字一起使用。 必须使用 SOCK_STREAM、SOCK_RDMSOCK_SEQPACKET 的套接字类型创建在 s 参数中传递套接字。

lpSendBuffer 参数指向建立连接后要发送的数据缓冲区。 dwSendDataLength 参数指定要发送的此数据的长度(以字节为单位)。 应用程序可以请求使用 ConnectEx 发送大型数据缓冲区,其方式与使用 sendWSASend 函数的方式相同。 但强烈建议开发人员不要使用 ConnectEx 在单个调用中发送大型缓冲区,因为此操作会使用大量的系统内存资源,直到发送整个缓冲区。

如果 ConnectEx 函数成功,则建立连接,并将 lpSendBuffer 参数指向的所有数据发送到 name 参数指向的 sockaddr 结构中指定的地址。

注意必须在运行时通过调用 WSAIoctl 函数并指定SIO_GET_EXTENSION_FUNCTION_POINTER操作码来获取 ConnectEx 函数的函数指针。 传递给 WSAIoctl 函数的输入缓冲区必须包含 WSAID_CONNECTEX,这是一个全局唯一标识符 (GUID) 其值标识 ConnectEx 扩展函数。 成功后, WSAIoctl 函数返回的输出包含指向 ConnectEx 函数的指针。 WSAID_CONNECTEX GUID 在 Mswsock.h 头文件中定义。
 

ConnectEx 函数使用重叠的 I/O。 因此, ConnectEx 函数使应用程序能够为大量线程相对较少的客户端提供服务。 相比之下, WSAConnect 函数(它不使用重叠的 I/O)通常需要一个单独的线程在同时收到请求时为每个连接请求提供服务。

注意 当给定线程退出时,将取消由给定线程启动的所有 I/O。 对于重叠套接字,如果在操作完成之前关闭线程,挂起的异步操作可能会失败。 有关详细信息 ,请参阅 ExitThread

 

面向连接的套接字通常无法立即完成其连接,因此会启动操作,并且函数会立即返回ERROR_IO_PENDING或WSA_IO_PENDING错误。 当连接操作完成并成功或失败时,将使用 lpOverlapped 中指示的完成通知机制报告状态。 与所有重叠函数调用一样,可以使用事件或完成端口作为完成通知机制。 GetQueuedCompletionStatusGetOverlappedResultWSAGetOverlappedResult 函数的 lpNumberOfBytesTransferred 参数指示请求中发送的字节数。

ConnectEx 函数成功完成后,套接字句柄 只能传递给以下函数:

如果在具有TF_DISCONNECT标志和TF_REUSE_SOCKET标志的以前连接的套接字上调用 TransmitFile 函数,则指定的套接字将返回到未连接但仍绑定的状态。 在这种情况下,套接字的句柄可以传递到其 s 参数中的 ConnectEx 函数,但套接字不能在 AcceptEx 函数调用中重复使用。 同样,使用 TransmitFile 函数重用的接受套接字不能用于 对 ConnectEx 的调用。 请注意,对于重复使用的套接字, ConnectEx 受基础传输行为的约束。 例如,TCP 套接字可能受 TCP TIME_WAIT状态的约束,从而导致 ConnectEx 调用延迟。

ConnectEx 函数返回 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 );

getsockopt 函数可与 SO_CONNECT_TIME 套接字选项一起使用,以检查 ConnectEx 正在进行时是否已建立连接。 如果已建立连接,则传递给 getsockopt 函数的 optval 参数中返回的值是套接字已连接的秒数。 如果未连接套接字,则返回的 optval 参数包含0xFFFFFFFF。 以这种方式检查连接是必要的,以确定连接是否已建立一段时间而不发送任何数据;在这种情况下,建议终止此类连接。

例如:


//Need to #include <mswsock.h> for SO_CONNECT_TIME

int seconds;
int bytes = sizeof(seconds);
int iResult = 0;

iResult = getsockopt( s, SOL_SOCKET, SO_CONNECT_TIME,
                      (char *)&seconds, (PINT)&bytes );
if ( iResult != NO_ERROR ) {
    printf( "getsockopt(SO_CONNECT_TIME) failed with error: %u\n", 
        WSAGetLastError() );
}
else {
    if (seconds == 0xFFFFFFFF)
        printf("Connection not established yet\n");
    else
       printf("Connection has been established %ld seconds\n",
           seconds);
}

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

如果 name 参数中指向的 sockaddr 结构的 address 参数全部为零,则 ConnectEx 将返回错误 WSAEADDRNOTAVAIL。 重新连接活动连接的任何尝试都将失败,错误代码为 WSAEISCONN

当连接的套接字因任何原因关闭时,建议丢弃该套接字并创建一个新套接字。 其原因是,最安全的假设是,当连接套接字由于任何原因而出现问题时,应用程序必须放弃套接字并再次创建所需的套接字,以便返回到稳定点。

如果使用 TF_REUSE_SOCKET 标志调用 DisconnectEx 函数,则指定的套接字将返回到未连接但仍绑定的状态。 在这种情况下,套接字的句柄可以传递给 ConnectEx 函数的 s 参数。

在 TCP 可以释放已关闭的连接并重用其资源之前必须经过的时间间隔称为TIME_WAIT状态或 2MSL 状态。 在此期间,与建立新连接相比,重新打开连接对客户端和服务器的成本要低得多。

TIME_WAIT行为在 RFC 793 中指定,该行为要求 TCP 在至少等于网络 MSL) 最大段生存期 (两倍的间隔内保持关闭连接。 释放连接后,其套接字对和用于套接字的内部资源可用于支持另一个连接。

Windows TCP 在连接关闭后还原为TIME_WAIT状态。 处于TIME_WAIT状态时,不能重复使用套接字对。 可以通过修改以下 DWORD 注册表设置来配置TIME_WAIT周期,该 DWORD 注册表设置表示以秒为单位的TIME_WAIT周期。

\ HKEY_LOCAL_MACHINE系统\CurrentControlSet\服务\TCPIP\参数\TcpTimedWaitDelay

默认情况下,MSL 定义为 120 秒。 TcpTimedWaitDelay 注册表设置默认为值 240 秒,表示 120 秒或 4 分钟的最大段生存期的 2 倍。 但是,可以使用此项来自定义间隔。

通过减小此项的值,TCP 可以更快地释放已关闭的连接,为新连接提供更多资源。 但是,如果该值过低,TCP 可能会在连接完成之前释放连接资源,从而要求服务器使用其他资源来重新建立连接。

可以将此注册表设置设置为 0 到 300 秒。

Windows Phone 8:Windows Phone 8 及更高版本上的 Windows Phone 应用商店应用支持此函数。

Windows 8.1Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本的 Windows 应用商店应用支持此函数。

要求

要求
最低受支持的客户端 Windows 8.1、Windows Vista [桌面应用 |UWP 应用]
最低受支持的服务器 Windows Server 2003 [桌面应用 | UWP 应用]
目标平台 Windows
标头 mswsock.h

另请参阅

AcceptEx

DisconnectEx

ExitThread

GetOverlappedResult

GetQueuedCompletionStatus

OVERLAPPED

ReadFile

TransmitFile

WSAConnect

WSAConnectByList

WSAConnectByName

WSAGetLastError

WSAIoctl

WSARecv

WSASend

WSAStartup

Winsock 函数

Winsock 参考

WriteFile

bind

closesocket

connect

getsockopt

recv

send

sendto

setsockopt

sockaddr