【问题标题】:winsock application and multhreading - listening to socket event from another threadwinsock 应用程序和多线程 - 从另一个线程监听套接字事件
【发布时间】:2012-12-04 08:07:45
【问题描述】:
假设我们有一个使用winsock 来实现tcp 通信的应用程序。
对于每个套接字,我们创建一个线程并在其上进行块接收。
当数据到达时,我们想通知其他线程(监听线程)。
我想知道实现这一点的最佳方法是什么:
放弃这种设计并使用非阻塞套接字,那么监听线程将不得不不断迭代并调用非阻塞接收,从而使其线程安全(套接字没有额外的线程)
使用异步过程调用来通知正在侦听的线程 - 这又将不得不等待 apc 为它们排队。
实现一些线程安全的消息队列,每个套接字线程将向其发布消息,并且监听器将再次检查它并从中提取数据。
另外,我阅读了有关 WSAAsyncSelect 的信息,但我看到它用于向窗口发送消息。其他线程没有类似的东西吗? (好吧,我猜 apc 是……)
谢谢!
【问题讨论】:
标签:
multithreading
winapi
winsock2
winsockets
【解决方案1】:
使用 I/O 完成端口。请参阅 Win32 API 的 CreateIoCompletionPort() 和 GetQueuedCompletionStatus() 函数(在文件管理函数下)。在这种情况下,使用套接字描述符代替文件句柄。
【解决方案2】:
最好将套接字 API 的机制(侦听、接受、读取和写入)抽象到与应用程序逻辑不同的层中。拥有一个捕获连接状态的对象,该状态是在传入连接期间创建的,您可以在此对象中维护传入和传出流量的缓冲区。这将允许您的网络接口层独立于应用程序代码。通过将应用程序功能与底层通信机制分离,这也将使代码更简洁。
阻塞或非阻塞套接字的决定取决于您的应用程序需要达到的可伸缩性级别。如果您的应用程序需要支持数百个传入连接,那么采用每套接字线程的方法并不是很明智。您最好选择基于 Io 端口的实现,这将使您的应用程序在增加代码复杂性的情况下具有极大的可扩展性。但是,如果您在任何时间点只能预见到几十个连接,您可以使用 Win32 事件或消息来使用异步套接字模型。基于 Win32 事件的方法不能很好地扩展超出某个限制,因为如果并发套接字的数量超过 63,您将不得不管理多个线程(因为 WaitForMultipleObjects 最多只能支持 64 个套接字)。但是,基于 Windows 消息的机制没有此限制。哦,基于 Win32 事件的方法不需要 GUI 窗口即可工作。
查看 WSAEventSelect 以及 MSDN 中的 WSAAsyncSelect API 文档。
您可能还想看看boost::asio 包。它通过套接字 API 提供了一个简洁(虽然有点复杂)的 C++ 抽象。