2011-02-18 146 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中定義的 錯誤。