在Win32中,有没有办法测试套接字是否是非阻塞的?

Dan*_*ach 10 sockets windows winapi winsock nonblocking

在Win32中,有没有办法测试套接字是否是非阻塞的?

在POSIX系统下,我会做类似以下的事情:

int is_non_blocking(int sock_fd) {
    flags = fcntl(sock_fd, F_GETFL, 0);
    return flags & O_NONBLOCK;
}
Run Code Online (Sandbox Code Playgroud)

但是,Windows套接字不支持fcntl().使用ioctl和FIONBIO 设置非阻塞模式,但似乎没有办法使用ioctl 获得当前的非阻塞模式.

在Windows上是否有其他一些调用我可以用来确定套接字当前是否处于非阻塞模式?

Dam*_*mon 7

稍微长一点的答案是:不,但你通常会知道它是否是,因为它的定义相对较好.

所有插座都明确阻止,除非你ioctlsocket()他们FIONBIO或者他们的手要么WSAAsyncSelectWSAEventSelect.后两个函数"秘密"将套接字更改为非阻塞.

既然您知道是否已经调用了这三个函数中的一个,即使您无法查询状态,它仍然是已知的.显而易见的例外是,如果该套接字来自某些第三方库,您不知道它对套接字做了什么.

旁注:有趣的是,套接字可以同时阻塞和重叠,这看起来并不直观,但它有点合理,因为它们来自相反的范例(准备与完成).

  • 如果我接受()一个连接,新套接字是否继承了监听套接字的非阻塞状态? (2认同)

Ent*_*ops 5

以前,您可以调用WSAIsBlocking来确定这一点.如果您正在管理遗留代码,这可能仍然是一个选项.

否则,您可以在套接字API上编写一个简单的抽象层.由于默认情况下所有套接字都是阻塞的,因此您可以维护内部标志并强制所有套接字操作通过您的API,以便您始终了解状态.

这是一个用于设置/获取阻止模式的跨平台代码段,尽管它并不能完全符合您的要求:

/// @author Stephen Dunn
/// @date 10/12/15
bool set_blocking_mode(const int &socket, bool is_blocking)
{
    bool ret = true;

#ifdef WIN32
    /// @note windows sockets are created in blocking mode by default
    // currently on windows, there is no easy way to obtain the socket's current blocking mode since WSAIsBlocking was deprecated
    u_long flags = is_blocking ? 0 : 1;
    ret = NO_ERROR == ioctlsocket(socket, FIONBIO, &flags);
#else
    const int flags = fcntl(socket, F_GETFL, 0);
    if ((flags & O_NONBLOCK) && !is_blocking) { info("set_blocking_mode(): socket was already in non-blocking mode"); return ret; }
    if (!(flags & O_NONBLOCK) && is_blocking) { info("set_blocking_mode(): socket was already in blocking mode"); return ret; }
    ret = 0 == fcntl(socket, F_SETFL, is_blocking ? flags ^ O_NONBLOCK : flags | O_NONBLOCK);
#endif

    return ret;
}
Run Code Online (Sandbox Code Playgroud)