【发布时间】:2010-10-20 01:54:59
【问题描述】:
有没有办法在 Windows 中找出套接字是否已经处于非阻塞模式?
我知道这可以在 Linux 的情况下完成,但是,我无法为这个 Windows 找到任何方法。
我所有的编码都是“C”语言。有什么办法吗?
【问题讨论】:
-
默认情况下,Windows 套接字是阻塞的(如 BSD 套接字)。你不能只用一个标志来跟踪吗?
有没有办法在 Windows 中找出套接字是否已经处于非阻塞模式?
我知道这可以在 Linux 的情况下完成,但是,我无法为这个 Windows 找到任何方法。
我所有的编码都是“C”语言。有什么办法吗?
【问题讨论】:
检查这一点的唯一方法是在非阻塞套接字上执行非法操作并检查它是否以预期的方式失败。几乎不是最坚固的设计。
除非您使用WSAIoctl 或ioctlsocket 和FIONBIO 将其显式设置为非阻塞,否则套接字将阻塞。我想,检查你的代码不会太难。如果您必须在运行时跟踪这一点,@jweyrich 建议的每个套接字的标志是可行的方法。
【讨论】:
刚刚回答了同样的问题here,所以这里复制粘贴,希望对您有所帮助:
以前,您可以致电WSAIsBlocking 来确定这一点。如果您正在管理遗留代码,这可能仍然是一个选项。
否则,您可以在套接字 API 上编写一个简单的抽象层。由于默认情况下所有套接字都是阻塞的,因此您可以维护一个内部标志并强制所有套接字操作通过您的 API,以便您始终了解状态。
这是一个用于设置/获取阻塞模式的跨平台 sn-p,尽管它在 Windows 上并不完全符合您的要求:
/// @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;
}
【讨论】:
来自MSDN,connect()的返回值:
在阻塞套接字上,返回值表示连接尝试成功或失败。
使用 非阻塞 套接字,无法立即完成连接尝试。在这种情况下,connect 将返回SOCKET_ERROR,WSAGetLastError() 将返回WSAEWOULDBLOCK。
【讨论】: