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