Winsock2 select():同一套接字上的多个事件可能吗?

Ger*_*nyi 1 c++ sockets select winsock2

根据此页面:

select 函数返回就绪且包含在 fd_set 结构中的套接字句柄总数。

SOCKET如果我只向每个FD_SETs 添加一个(且相同)并将它们传递给 ,那么理论上返回值是否可能大于 1 select?这意味着我必须在同一个套接字上处理多个事件。例子:

SOCKET someRandomSocket;

FD_SET readfds;
FD_SET writefds;
FD_SET exceptfds;

timeval timeout;
/* ...
Connecting someRandomSocket to another peer.
... */

FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);

FD_SET(someRandomSocket, &readfds);
FD_SET(someRandomSocket, &writefds);
FD_SET(someRandomSocket, &exceptfds);

int total = select(0, &readfds, &writefds, &exceptfds, &timeout);

/* total > 1 is possible? */
/* (FD_ISSET(someRandomSocket, &exceptfds) && (FD_ISSET(someRandomSocket, &readfds) || FD_ISSET(someRandomSocket, &writefds)) == true) possible? */
Run Code Online (Sandbox Code Playgroud)

还有一个问题:是否有可能发生我必须同时处理同一个套接字上的异常和非异常事件的情况?

Rem*_*eau 5

SOCKET如果我只向每个FD_SETs 添加一个(且相同)并将它们传递给 ,那么理论上返回值是否可能大于 1 select?这意味着我必须在同一个套接字上处理多个事件。

无论返回值select()是否多次计数(这很容易测试),您都应该忽略实际数字。SOCKET> 0 的返回值只是告诉您fd_sets 中的任何一个包含与请求的事件匹配的套接字(select()修改fd_sets 以删除不匹配的套接字)。即使您知道套接字总数,您仍然必须使用 检查各个套接字FD_ISSET(),因此返回值 > 0 时的实际数量在实际处理中意义不大。只有 -1(错误)、0(超时)和 > 0(存在事件)才有意义。

是的,一个套接字可以同时启用多个事件。例如,套接字可以同时可读和可写。

例如:

FD_SET readfds;
FD_SET writefds;
FD_SET exceptfds;

FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);

FD_SET(someRandomSocket, &readfds);
FD_SET(someRandomSocket, &writefds);
FD_SET(someRandomSocket, &exceptfds);

timeval timeout;
timeout.tv_sec = ...;
timeout.tv_usec = ...;

int total = select(0, &readfds, &writefds, &exceptfds, &timeout);

if (total == -1)
{
    // error in select() itself, handle as needed...
}
else if (total == 0)
{
    // timeout, handle as needed...
}
else
{
    if (FD_ISSET(someRandomSocket, &exceptfds) )
    {
        // socket has inbound OOB data, or non-blocking connect() has failed, or some other socket error, handle as needed...
    }

    if (FD_ISSET(someRandomSocket, &readfds) )
    {
        // socket has inbound data, or has disconnected gracefully, handle as needed...
    }

    if (FD_ISSET(someRandomSocket, &writefds) )
    {
        // socket is writable, or non-blocking connect() has succeeded, handle as needed...
    }
}
Run Code Online (Sandbox Code Playgroud)

是否有可能发生我必须同时处理同一个套接字上的异常和非异常事件的情况?

这取决于异常的性质。并非所有异常都是致命错误。