2011-02-18 57 views

回答

8

的Windows支持Socket几种操作模式,你也需要明确您所使用的一个:

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

就便利性而言,异步套接字非常简单,并且由MFC CAsyncSocket类支持。

事件套接字是棘手,因为通行到WaitForMultipleObjects的对象的最大使用数量为32

重叠插槽,IO CompletionPorts,是处理插座最可扩展的方式,并允许基于Windows的服务器扩展到几十数千个插座。


根据我的经验,使用异步套接字的时候,下面的事情浮现在脑海中:

  • 通过窗口消息处理FD事件可以处理插座的“手”,但性能将开始遭受因为所有事件处理都在一个线程中完成,通过消息队列进行序列化,如果在单个线程GUI应用程序中使用该消息队列,该消息队列可能正忙于处理UI事件。

  • 如果您在同一个线程很多插座上托管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是你的朋友

+0

我的目标是异步套接字,我不知道使用事件会限制我。所以我会创建一个消息窗口。我将如何去处理不同的套接字(例如:多个连接)。 PS:我为了清晰起见编辑帖子。 – 2011-02-18 06:04:42

0

你告诉WSAAsyncSelect()发送将指定触发该消息插座窗口消息的wParam参数。这在WSAAsyncSelect()documentation明确提出:

当指定网络上的指定的套接字 小号发生 事件之一,应用程序窗口的hWnd接收 消息WMSG。 wParam 参数标识发生网络事件的 上的套接字。 lParam的低位字指定发生的 网络事件。 lParam的高位字 包含任何错误 的代码。错误代码为Winsock2.h中定义的 错误。