【发布时间】:2011-02-18 05:05:52
【问题描述】:
我正在使用消息窗口和 WSAAsyncSelect。如何使用一个消息窗口跟踪多个套接字(客户端)?
【问题讨论】:
标签: c windows sockets winsock2
我正在使用消息窗口和 WSAAsyncSelect。如何使用一个消息窗口跟踪多个套接字(客户端)?
【问题讨论】:
标签: c windows sockets winsock2
Windows 支持多种套接字操作模式,您需要明确自己使用的是哪一种:
为了方便,异步套接字比较简单,MFC CAsyncSocket 类支持。
事件套接字很难使用,因为可传递给 WaitForMultipleObjects 的最大对象数为 64。
使用 IO CompletionPorts 的重叠套接字是处理套接字的最具可扩展性的方式,它允许基于 Windows 的服务器扩展到数万个套接字。
根据我的经验,在使用异步套接字时,会想到以下几点:
通过窗口消息处理 FD 事件可以处理“大量”套接字,但性能将开始受到影响,因为所有事件处理都在一个线程中完成,并通过可能忙于处理 UI 事件的消息队列进行序列化如果在单线程 GUI 应用中使用。
如果您将 GUI 窗口或计时器托管在与许多套接字相同的线程上:WM_TIMER 和 WM_PAINT 消息的优先级较低,只有在消息队列为空时才会生成。因此,非常繁忙的套接字会导致 GUI 绘制或基于 SetTimer 的计时失败。
如果托管 GUI 可以解决这些问题,请创建一个专用的工作线程来处理您的套接字。鉴于工作线程将有一个消息循环,您可以使用消息队列进行线程间通信 - 只需将 WM_APP 消息发布到线程。
将 FD 回调映射到套接字对象的最简单方法是为每个将接收消息的 HWND 创建一个 SocketObjects 数组,然后在每次调用 WASAsyncSelect 时使用 WM_USER+index 作为消息 ID。然后,当您收到 WM_USER 到 WM_USER+(数组大小)范围内的消息时,您可以快速提取相应的状态对象。 WM_USER 为 0x400,WM_APP 为 0x8000,因此您可以使用此方法为每个消息窗口索引多达 31744 个套接字。
不要使用静态范围数组。您需要将数组与窗口相关联,因为您可能希望在多个线程上创建套接字。每个线程都需要自己的消息循环和消息窗口。
HWND_MESSAGE 是你的朋友
【讨论】:
您告诉WSAAsyncSelect() 发送的窗口消息的wParam 参数将指定触发消息的套接字。这在WSAAsyncSelect()documentation中有明确说明:
当提名网络之一 事件发生在指定的套接字上 s、应用程序窗口hWnd 接收消息 wMsg。 wParam 参数标识上的套接字 发生了网络事件。 lParam 的低位字指定 发生的网络事件。这 lParam 的高位字包含任何错误 代码。错误代码是任何错误 在 Winsock2.h 中定义。
【讨论】: