没有 ConnectEx 的 Windows 上的非阻塞套接字连接
Posted
技术标签:
【中文标题】没有 ConnectEx 的 Windows 上的非阻塞套接字连接【英文标题】:Non-blocking socket connect on Windows without ConnectEx 【发布时间】:2011-10-23 13:45:58 【问题描述】:我需要在单个进程中启动 1000 个 client 连接,我需要解决的关键限制是驱动程序不支持 ConnectEx,因此我无法拥有纯 IOCP 解决方案。
我的第一个想法是处理连接的线程池,其中每个句柄可以使用普通的连接/选择语义处理多达 64 个连接,并且一旦连接就继续使用 IOCP。 但这行不通;一旦选择运行,我就无法向 FD_SET 添加另一个套接字。所以我必须将套接字设置为非阻塞并轮询它们。 最好的解决方案可能是最简单的;每个线程一个连接客户端。假设我可以保持合理的连接率,那么池中的线程数可能会很少。
这是一种奇怪的情况,理想情况下,驱动程序会支持 ConnectEx,但它(目前)不支持,我需要以最好的方式解决它。
还有其他方法吗?
【问题讨论】:
【参考方案1】:首先,可以使用虚拟套接字(例如,连接到自身的 UDP 套接字)破坏 select
,尽管在您的情况下这可能代价高昂。
如果你有一个可以处理周围消息的窗口,你可以使用WSAAsyncSelect
来获取connect
的异步通知。 (请注意,这也会自动使您的套接字非阻塞,这需要再次调用 WSAAsyncSelect
并调用 ioctlsocket
来禁用)。
如果没有这个,您可以使用WSAEventSelect
,但您会发现这会将您限制为每次等待 64 个套接字(因为这是WaitForMultipleObjects
的上限)。这也将使您的套接字成为非阻塞的,您可以像为 WSAAsyncSelect
所做的那样撤消它。
(作为一个完整的旁注,您可以通过在包含winsock2.h
之前定义FD_SETSIZE
来增加select
处理的套接字数量)
【讨论】:
WSAAsyncSelect 和 WSAEventSelect 听起来都很有用。我想我将从每个连接一个线程开始,然后使用这两个中的一个将连接池化为 64 个组。谢谢。 我没有注意到 WSAAsyncSelect 使用 Windows 消息。讨厌,但可能很有帮助。以上是关于没有 ConnectEx 的 Windows 上的非阻塞套接字连接的主要内容,如果未能解决你的问题,请参考以下文章
无法连接服务器: dial tcp [::1]:8080: connectex: No connection could be made because the target machine主动拒绝
Windows系统下Log4Net+FileBeat+ELK日志分析系统问题总结