一、WSAPoll 函数Linux 系统上的 poll 函数,在 Windows 上对应着 WSAPoll 函数,你可能在一些开源的 pc 端软件中看到该函数的用法。这个函数是在 Windows Vista 和 Windows Server 2008 及以后版本引入的,也就是说在 Windows XP 和 Windows Server 2003 不可用。
WSAPoll 的函数签名如下:
1int WSAAPI WSAPoll(2 LPWSAPOLLFD fdArray,3 ULONG fds,4 INT timeout5);参数 fdArray 类型是结构体 WSAPOLLFD 指针类型,实际是结构体 WSAPOLLFD 数组;
参数 fds 类型是 fdArray 数组元素的个数;
参数 timeout 表示 WPAPoll 函数的等待超时时间,单位为毫秒,如果设置为大于 0 值,则为需要等待的超时时间,如果设置为等于 0 值,则 WSAPoll 函数会立即返回,如果设置为小于 0 值,则 WSAPoll 在没有事件触发的情况下会无限等待下去。
返回值:返回 0 表示在等待时间内 fdArray 中没有一个 socket 有关注的事件触发;返回小于 -1( SOCKET_ERROR ),表示 WSAPoll 函数调用出错,可以使用 WSAGetLastError 函数获取错误码;返回大于 0 值表示 fdArray 中关注的事件触发的 socket 数目。
WSAPOLLFD 的定义如下:
1typedef struct pollfd {2 SOCKET fd;3 SHORT events;4 SHORT revents;5} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;字段 fd 是对应的 socket 句柄,字段 events 和 revents 分别是需要关注 socket 事件和 WSAPoll 函数返回后的触发事件标志。events 字段可设置的事件标志如下:
FlagMeaningPOLLRDBANDPriority band (out-of-band) data can be read without blocking.POLLRDNORMNormal data can be read without blocking.POLLWRNORMNormal data can be written without blocking.revents 字段的事件标志取值列表如下:
FlagDescriptionPOLLERRAn error has occurred.POLLHUPA stream-oriented connection was either disconnected or aborted.POLLNVALAn invalid socket was used.POLLRDBANDPriority band (out-of-band) data may be read without blocking.POLLRDNORMNormal data may be read without blocking.POLLWRNORMNormal data may be written without blocking.上面的英文描述都是浅显易懂的,这里就不再翻译。其中 POLLRDNORM 是读事件,POLLWRNORM 是写事件,POLLERR 是出错事件。
当 WSAPoll 函数返回时,如果某个 socket 既没有出错,也无关心的事件触发,则 revents 被设置为 0。
WSAPoll 示例代码如下:
1WSAPOLLFD fdArray[2]; 2 3fdArray[0].fd = somesocket1; 4fdArray[0].events = POLLRDNORM | POLLWRNORM; 5 6fdArray[1].fd = somesocket2; 7fdArray[1].events = POLLRDNORM | POLLWRNORM; 8 9//无限等待直到事件触发10WPAPoll(fdArray, 2, -1);11for (int i = 0; i 2; ++i)12{13 if (fdArray[i].revents | POLLRDNORM)14 {15 //处理可读事件16 }1718 if (fdArray[i].revents | POLLWRNORM)19 {20 //处理可写事件21 }2223 if (fdArray[i].revents | POLLERR)24 {25 //处理出错事件26 }27}二、WSAPoll 与 poll 的区别Windows 的 WSAPoll 函数虽然和 Linux 的 poll 函数用法上基本相同,但是还是有个用法上的差别,对于 Linux poll 函数,我们可以不给其设置任何 fd,这样直接将其当作一个等待超时函数使用。这种情况也很常见,例如服务器端使用 poll 模型时没有任何客户端连接上来时。即:
1//等待 10 毫秒后返回2poll(NULL, 0, 10);3//一直阻塞4poll(NULL, 0, -1);但同样的代码:
1//等待 10 毫秒后返回2WSAPoll(NULL, 0, 10);3//一直阻塞4WSAPoll(NULL, 0, -1);这样的代码是无法达到预期目的的。Windows 的 WSAPoll 函数第一个参数必须至少含有一个有效的 socket 句柄才能正常运行,而 Linux poll 函数没有这个限制。
推荐阅读:
如何调试多线程程序陈芳,高考之后我要学计算机专业,将来干IT发财了,我就娶你!使用 gdb 调试多进程程序 —— 以调试 nginx 为例为何要将 listenfd 设置成非阻塞的?玩知乎五年,我在知乎赚了多少钱?原创不易,点个在看呗~