select 函数 (winsock2.h)

select 函数确定一个或多个套接字的状态,并在必要时等待执行同步 I/O。

语法

int WSAAPI select(
  [in]      int           nfds,
  [in, out] fd_set        *readfds,
  [in, out] fd_set        *writefds,
  [in, out] fd_set        *exceptfds,
  [in]      const timeval *timeout
);

参数

[in] nfds

已忽略。 包含 nfds 参数只是为了与 Berkeley 套接字兼容。

[in, out] readfds

一个可选指针,指向要检查的一组套接字的可读性。

[in, out] writefds

指向要检查可写性的一组套接字的可选指针。

[in, out] exceptfds

指向要检查错误的一组套接字的可选指针。

[in] timeout

选择等待的最长时间,以 TIMEVAL 结构的形式提供。 将阻止操作的 超时 参数设置为 null

返回值

select 函数返回fd_set结构中已就绪并包含的套接字句柄总数;如果时间限制过期,则返回 0;如果发生错误,则返回SOCKET_ERROR。 如果返回值SOCKET_ERROR,则 WSAGetLastError 可用于检索特定的错误代码。

错误代码 含义
WSANOTINITIALISED
在使用此函数之前,必须成功调用 WSAStartup
WSAEFAULT
Windows 套接字实现无法为其内部操作分配所需的资源,或者 readfdswritefdsexceptfdstimeval 参数不是用户地址空间的一部分。
WSAENETDOWN
网络子系统失败。
WSAEINVAL
超时值无效,或者三个描述符参数全部为 null
WSAEINTR
阻止的 Windows 套接字 1.1 调用已通过 WSACancelBlockingCall 取消。
WSAEINPROGRESS
阻止 Windows Sockets 1.1 调用正在进行,或者服务提供程序仍在处理回调函数。
WSAENOTSOCK
其中一个描述符集包含不是套接字的条目。

注解

select 函数用于确定一个或多个套接字的状态。 对于每个套接字,调用方可以请求有关读取、写入或错误状态的信息。 请求给定状态的套接字集由 fd_set 结构指示。 包含在 fd_set 结构中的套接字必须与单个服务提供程序相关联。 出于此限制的目的,如果描述其协议 的WSAPROTOCOL_INFO 结构具有相同的 providerId 值,则将套接字视为来自同 一服务 提供程序。 返回后,将更新结构以反映满足指定条件的这些套接字的子集。 select 函数返回满足条件的套接字数。 提供了一组宏用于操作 fd_set 结构。 这些宏与伯克利软件中使用的宏兼容,但基础表示形式完全不同。

参数 readfds 标识要检查的可读性套接字。 如果套接字当前处于 侦听 状态,则如果已收到传入的连接请求,则它将标记为可读,以便保证 接受 在不阻塞的情况下完成。 对于其他套接字,可读性意味着排队的数据可用于读取,以便保证不阻止对 recvWSARecv、WSARecvFromrecvfrom 的调用。

对于面向连接的套接字,可读性还可以指示已从对等方收到关闭套接字的请求。 如果虚拟线路正常关闭,并且接收了所有数据,则 recv 将立即返回且读取零个字节。 如果重置了虚拟线路,则 recv 将立即完成,错误代码为 WSAECONNRESET。 如果已启用套接字选项SO_OOBINLINE,将检查 OOB 数据是否存在 (请参阅 setsockopt) 。

参数 writefds 标识要检查的可写性套接字。 如果套接字正在处理 (非阻止) 的连接 调用,则如果连接建立成功完成,则套接字是可写的。 如果套接字未处理 连接 调用,可写性意味着 可以保证 sendsendtoWSASendto 成功。 但是,如果 len 参数超过可用的传出系统缓冲区空间量,则它们可以在阻止套接字上阻塞。 未指定可以假定这些保证有效多长时间,尤其是在多线程环境中。

参数 exceptfds 标识要检查的套接字是否存在 OOB 数据或任何异常错误条件。

注意 仅当选项SO_OOBINLINE为 FALSE 时,才会以这种方式报告带外数据。 如果套接字正在处理 (非阻止) 的连接 调用,则连接尝试失败的 指示 (应用程序 必须调用 getsockopt SO_ERROR来确定错误值,以描述) 失败的原因。 本文档不定义将包含哪些其他错误。
 
任何两个参数( readfdswritefdsexceptfds)都可以指定为 null。 必须至少有一个非 null,并且任何非 null 描述符集必须至少包含一个套接字的句柄。

总之,如果出现如下情况, 则 select 返回时,将在特定集中标识套接字:

readfds

  • 如果已调用 侦听 且连接挂起, 则接受 将成功。
  • 如果) 启用SO_OOBINLINE,则数据可用于读取 (包括 OOB 数据。
  • 连接已关闭/重置/终止。
writefds
  • 如果处理 连接 调用 (非阻止) ,则表示连接已成功。
  • 可以发送数据。
exceptfds
  • 如果处理 连接 调用 (非阻止) ,则连接尝试失败。
  • 仅当) 禁用SO_OOBINLINE时,OOB 数据才可用于读取 (。
头文件 Winsock2.h 中定义了四个宏,用于操作和检查描述符集。 变量FD_SETSIZE确定集中描述符的最大数目。 (FD_SETSIZE 的默认值为 64,可通过先将FD_SETSIZE定义为另一个值进行修改,然后再包括 Winsock2.h.) 内部, fd_set 结构中的套接字句柄不如在 Berkeley Unix 中表示为位标志。 其数据表示是不透明的。 使用这些宏将保持不同套接字环境之间的软件可移植性。 用于操作和检查fd_set内容的宏包括:
  • FD_ZERO (*set) - 初始化设置为空集。 在使用之前,应始终清除集。
  • FD_CLR (,*set) - 从集中删除套接字。
  • FD_ISSET (,*set) - 检查是否为 set 的成员,如果为 ,则返回 TRUE。
  • FD_SET (,*set) - 添加要设置的套接字。

参数 超时 控制 选择 需要多长时间才能完成。 如果 超时 指针, 则 select 将无限期阻止,直到至少有一个描述符满足指定条件。 否则, 超时 将指向 TIMEVAL 结构,该结构指定 选择 在返回之前应等待的最长时间。 当 select 返回时,不会更改 TIMEVAL 结构的内容。 如果 TIMEVAL 初始化为 {0, 0}, 则 select 将立即返回;用于轮询所选套接字的状态。 如果 select 立即返回,则 select 调用被视为非阻止调用,且非阻止调用的标准假设适用。 例如,不会调用阻塞挂钩,并且 Windows 套接字不会生成。

注意select 函数对向 WSAAsyncSelect 或 WSAEventSelect 注册的套接字事件的持久性没有影响。
 
注意发出阻止 Winsock 调用时,例如 select,超时参数设置为 NULL 时,Winsock 可能需要等待网络事件,然后调用才能完成。 在这种情况下,Winsock 执行可发出警报的等待, (在同一线程上计划的 APC) 异步过程调用可能会中断该等待。 在 APC 内发出另一个阻止 Winsock 调用,该调用中断了同一线程上正在进行的阻止 Winsock 调用将导致未定义的行为,并且 Winsock 客户端绝不能尝试。
 
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
标头 winsock2.h
Library Ws2_32.lib
DLL Ws2_32.dll

另请参阅

TIMEVAL

WSAAsyncSelect

WSAEventSelect

Winsock 函数

Winsock 参考

accept

connect

recv

recvfrom

send