在Win32中,有没有办法测试套接字是否是非阻塞的?
在POSIX系统下,我会做类似以下的事情:
int is_non_blocking(int sock_fd) {
flags = fcntl(sock_fd, F_GETFL, 0);
return flags & O_NONBLOCK;
}
但是,Windows套接字不支持fcntl()。非阻塞模式设置使用带有FIONBIO的ioctl,但似乎没有办法使用ioctl 获取当前的非阻塞模式。
我是否可以使用Windows上的其他调用来确定套接字当前是否处于非阻塞模式?
答案 0 :(得分:7)
稍微长一点的答案是:不,但你通常会知道它是否是,因为它的定义相对较好。
除非您使用ioctlsocket()
明确FIONBIO
他们,否则所有套接字都会被屏蔽,或者将其移至WSAAsyncSelect
或WSAEventSelect
。后两个函数“秘密”将套接字更改为非阻塞。
既然您知道是否已经调用了这三个函数中的一个,即使您无法查询状态,它仍然是已知的。明显的例外是,如果该套接字来自某些第三方库,您不知道它对套接字究竟做了什么。
旁注:有趣的是,套接字可以同时阻塞和重叠,这看起来并不直观,但它有点合理,因为它们来自相反的范例(准备就绪与完成)。
答案 1 :(得分: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;
}
答案 2 :(得分:0)
我同意接受的答案,没有正式的方法可以确定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 */
}
注意事项: