Windows 在Win32中,是否有方法测试套接字是否为非阻塞的?

Windows 在Win32中,是否有方法测试套接字是否为非阻塞的?,windows,winapi,sockets,winsock,nonblocking,Windows,Winapi,Sockets,Winsock,Nonblocking,在Win32中,是否有方法测试套接字是否为非阻塞的 在POSIX系统下,我将执行以下操作: int is_non_blocking(int sock_fd) { flags = fcntl(sock_fd, F_GETFL, 0); return flags & O_NONBLOCK; } 但是,Windows套接字不支持fcntl()。非阻塞模式是使用ioctl和FIONBIO设置的,但似乎没有办法使用ioctl获取当前的非阻塞模式 我是否可以使用Windows上的其

在Win32中,是否有方法测试套接字是否为非阻塞的

在POSIX系统下,我将执行以下操作:

int is_non_blocking(int sock_fd) {
    flags = fcntl(sock_fd, F_GETFL, 0);
    return flags & O_NONBLOCK;
}
但是,Windows套接字不支持fcntl()。非阻塞模式是使用ioctl和FIONBIO设置的,但似乎没有办法使用ioctl获取当前的非阻塞模式


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

稍长一点的回答是:否,但您通常会知道它是否处于非阻塞模式,因为它的定义相对较好

除非您使用
FIONBIO
显式地
ioctlsocket()
它们,或者将它们交给
WSAAsyncSelect
WSAEventSelect
。后两个函数“秘密”将套接字更改为非阻塞

因为您知道是否调用了这3个函数中的一个,即使您无法查询状态,它仍然是已知的。一个明显的例外是,如果该套接字来自某个第三方库,而您不知道它到底对该套接字做了什么


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

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

否则,您可以在套接字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;
}

我同意公认的答案,没有官方方法确定Windows上套接字的阻塞状态。如果您从第三方获得套接字(比方说,您是TLS库,从上层获得套接字),您无法确定它是否处于阻塞状态

尽管如此,我有一个工作,非官方的和有限的解决方案的问题,这对我来说工作了很长一段时间

我尝试从套接字读取0字节。如果是阻塞套接字,它将返回0;如果是非阻塞套接字,它将返回-1,GetLastError等于WSAEWOULDBLOCK

int IsBlocking(SOCKET s)
{
    int r = 0;
    unsigned char b[1];
    r = recv(s, b, 0, 0);
    if (r == 0)
        return 1;
    else if (r == -1 && GetLastError() == WSAEWOULDBLOCK)
        return 0;
    return -1; /* In  case it is a connection socket (TCP) and it is not in connected state you will get here 10060 */
}
注意事项:

  • 使用UDP套接字
  • 适用于连接的TCP套接字
  • 不适用于未连接的TCP套接字
如果我接受()连接,新套接字是否继承侦听套接字的非阻塞状态?