如何映射 POSIX 的 select 和 Windows WSAEventSelect 的事件

Posted

技术标签:

【中文标题】如何映射 POSIX 的 select 和 Windows WSAEventSelect 的事件【英文标题】:How to map events of POSIX's select and Windows WSAEventSelect 【发布时间】:2016-01-27 16:54:52 【问题描述】:

POSIX 的 select 允许确定 3 个事件:

阅读 写 错误

Window 的 WSAEventSelect 有 10 个:

FD_READ FD_WRITE FD_OOB FD_ACCEPT FD_CONNECT FD_CLOSE FD_QOS FD_GROUP_QOS FD_ROUTING_INTERFACE_CHANGE FD_ADDRESS_LIST_CHANGE

如何将这些 Windows 事件映射到 POSIX 事件?

编辑

很遗憾,由于multiple providers restriction,我无法使用Windows 的select 实现。

【问题讨论】:

如果您不需要使用 WSAEVENT 等待网络事件,您也可以使用 select(..) ...它在 winsock2.h 中定义 @LukasThomsen 我不能使用select,因为它不允许混合来自不同提供商的套接字。 【参考方案1】:

select()WSAEventSelect() 之间的映射如果您阅读文档并不难弄清楚。

select function

WSAEventSelect function

select() 报告套接字在以下情况下是可读的:

    套接字正在侦听,并且有等待接受的待处理入站连接 (FD_ACCEPT) 套接字有等待读取的待处理数据 (FD_READ)。如果在套接字上启用了SO_OOBINLINE 选项,则这包括带外数据。 套接字已被对等方正常关闭(FD_CLOSE,它也处理一些不正常的关闭)。

select() 报告套接字在以下情况下是可写的:

    非阻塞connect() 已成功连接到侦听端口(@98​​7654334@,错误代码为零) 套接字在被接受后有缓冲区空间来接受出站数据 (FD_WRITE),或者在之前的非阻塞发送后将不再阻塞。

select() 在以下情况下报告套接字异常:

    非阻塞connect() 失败(FD_CONNECT 带有非零错误代码)。您可以使用getsockopt(SOL_SOCKET, SO_ERROR) 获取错误代码。 如果在套接字 (FD_OOB) 上禁用了 SO_OOBINLINE 选项,则套接字有等待读取的未决带外数据。 出现各种套接字错误。

其余的 WSA 事件没有 select() 等效项,因为它们是与 POSIX/BSD 套接字 API 无关的严格的 WinSock 特定扩展。

因此,您将使用WSAEventSelect() 设置所需的FD_... 事件,然后使用WSAWaitForMultipleEvents() 等待事件。当事件发出信号时,使用WSAEnumNetworkEvents() 获取关联的错误代码并清除事件状态以等待下一次等待。

【讨论】:

如何确定连接失败并显示错误代码? 这个映射的来源是什么? @Kentzo:MSDN 文档。 每个事件都可能因错误而失败,但您只提到了FD_CONNECT。为什么不提其余的? @Kentzo:select() 不会区分特定事件的错误,而 WSAEventSelect() 会。至少对于connect(),如果连接尝试成功,select() 报告可写,否则报告异常状态,因此您可以区分(您必须使用getsockopt(SOL_SOCKET, SO_ERROR) 来获取实际的错误代码)。我确实说过“当一个事件发出信号时,使用 WSAEnumNetworkEvents() 来获取相关的错误代码”。您问如何将 WSAEventSelect() 事件映射到 select(),而不是反过来。

以上是关于如何映射 POSIX 的 select 和 Windows WSAEventSelect 的事件的主要内容,如果未能解决你的问题,请参考以下文章

Linux 中的 select()、posix 消息队列和多线程

mingw-w64 线程:posix vs win32

Posix共享内存

有人用过Posix pthread win32库,dll文件

在 Win32/MFC 和 POSIX 中,线程会自行清理吗?

mingw-w64线程模型:posix vs win32(posix允许使用c++11的std:: thread,但要带一个winpthreads,可能需要额外dll)