在WinSock中处理异步套接字?

Jas*_*ich 4 c sockets windows winsock2

我正在使用消息窗口和WSAAsyncSelect.如何通过一个消息窗口跟踪多个套接字(客户端)?

Chr*_*cke 13

Windows支持多种套接字操作模式,您需要清楚使用哪种模式:

  • 阻塞套接字.发送和recv块.
  • 非阻塞套接字:send和recv返回E_WOULDBLOCK,select()用于确定哪些套接字已准备就绪
  • 异步套接字:WSAAsyncSelect - 套接字将事件通知发送到HWND.
  • EventSockets:WSAEventSelect - 套接字信号事件.
  • 重叠套接字:WSASend和WSARecv通过传入OVERLAPPED结构与套接字一起使用.重叠套接字可与IOCompletionPorts结合使用,并提供最佳可扩展性.

在方便性方面,异步套接字很简单,并且由MFC CAsyncSocket类支持.

事件套接字很难使用,因为可传递给WaitForMultipleObjects的最大对象数是64.

具有IO CompletionPorts的重叠套接字是处理套接字的最可扩展方式,并允许基于Windows的服务器扩展到数万个套接字.


根据我的经验,在使用Async Sockets时,会想到以下几点:

  • 通过窗口消息处理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是你的朋友