2011-03-30 41 views
9

在Win32中,有没有一种方法可以测试套接字是否为非阻塞?在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调用,我可以用它来确定套接字当前处于非阻塞模式?

回答

6

稍微长一点的答案是:不,但通常你会知道它是否是因为它相对明确。

所有的套接字都被阻塞,除非您明确地使用与FIONBIO或将它们交给WSAAsyncSelectWSAEventSelect。后两个函数“偷偷”将套接字更改为非阻塞。

既然你知道你是否已经调用了这三个函数之一,即使你不能查询状态,它仍然是已知的。明显的例外情况是,如果该套接字来自某个第三方库,其中您不知道该套接字究竟做了什么。有趣的是,套接字可以同时被阻塞和重叠,这看起来并不直观,但它有道理,因为它们来自相反的范例(准备vs完成)。

+1

如果我接受()的连接,并在新的套接字继承监听套接字的非阻塞状态? – 2011-04-01 17:00:29

2

以前,您可以拨打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; 
} 
相关问题