HP-Socket 是一套通用的高效能 Windows Socket 組件包,包含服務端組件(IOCP 模型)和用戶端組件(Event Select 模型),廣泛適用於 Windows 平台的 TCP 通訊系統。HP-Socket 對通訊層實現完全封裝,上層應用不必關注通訊層的任何細節;HP-Socket 提供基於事件通知模型的 API 介面,能非常簡單高效地整合到各類應用程式中;另外,為了讓大家能更方便的學習 HP-Socket,特此精心製作了一個功能測試樣本(Test Echo)一個效能測試樣本(Test Echo-PFM)和一個 PULL 模型測試樣本(Test Echo-Pull),使用者可以通過這兩個測試樣本入手,迅速掌握組件的設計思想和使用方法。
----------------------------------------------------------------
通用性
- 通訊組件的唯一職責就是接受和發送位元組流,絕對不能參與上層協議解析等工作;
- 與上層使用者解耦、互不依賴,組件與使用者通過操作介面和監聽器介面進行互動,組件實現操作介面為上層提供操作方法;使用者實現監聽器介面把自己註冊為組件的 Listener,接收組件通知。因此,任何使用者只要實現了監聽器介面都可以使用組件;另一方面,甚至可以自己重新寫一個實現方式完全不同的組件實現給使用者調用,只要該組件遵從組件的操作介面,這也是 DIP 設計原則的體現。
可用性
可用性對所有萬用群組件都是至關重要的,如果太難用還不如自己重頭寫一個來得方便。因此,組件的操作介面和監聽器介面設計得盡量簡單易用(通俗來說就是“傻瓜化”),這兩個介面的主要方法均不超過 5 個。另外,組件完全封裝了所有的底層 Socket 通訊,上層應用看不到任何通訊細節,不必也不能干預任何通訊操作,Socket 串連被抽象為 Connection ID,該參數作為串連標識提供給上層應用識別不同的串連。
高效能
作為底層的萬用群組件,效能問題是必須考慮的,絕對不能成為系統的瓶頸。而另一方面,從實際出發,根據用戶端組件與服務端組件的效能要求採用不同的 Socket 模型。組件在設計上充分考慮了效能、現實使用情景、可用性和實現複雜性等因素,確保滿足效能要求的同時又不會寫得太複雜。做出以下兩點設計決策:
- 用戶端:在單獨線程中實現 Socket 通訊互動。這樣可以避免與主線程或其他線程相互幹擾;I/O 模型選擇 Event Select 通訊模型。
- 服務端:採用 Windows 平台效率最高的 IOCP 通訊模型;利用緩衝池技術,在通訊的過程中,通常需要頻繁的申請和釋放記憶體緩衝區,建立了動態緩衝池, 只有當緩衝池中沒有可用對象時才建立新對象,而當緩衝對象過多時則會壓縮緩衝池;另外,組件的動態記憶體通過私人堆(Private Heap)機制分配,避免與 new / malloc 競爭同時又減少記憶體空洞。
伸縮性
可以根據實際的使用環境要求設定組件的各項績效參數(如:背景工作執行緒的數量、各種緩衝池的大小、收發緩衝區的大小、Socket 監聽隊列的大小、Accep 派發的數目以及心跳檢查的間隔等)。
(項目首頁:點擊這裡,:點擊這裡)
PUSH / PULL 模型簡介:
通訊組件向上層應用提交資料有以下兩種模式:
- PUSH 模型:當通訊組件接收到資料後調用應用介面的 OnReceive(dwConnID, const BYTE* pData, int iLength) 方法嚮應用程式推送資料,應用程式實現該方法並在方法內部取得 pData 進行處理。
- PULL 模型:當通訊組件接收到資料後調用應用介面的 OnReceive(dwConnID, int iTotalLength) 方法(注意,不包含 pData 參數)通知應用程式有 iLength 長度的資料可取,如果應用程式認為該長度的資料能組成一個完整的資料包則調用通訊組件的 Fetch(BYTE* pData, int iDataLength) 方法抓取 iDataLength 長度的資料(iDataLength <= iTotalLength)。
其中 PUSH 模型效率相對較高,但應用程式本身要負責處理解包和粘包等問題,帶來一定的複雜性;PULL 模型則相對簡單,只要上層協議定義得足夠嚴謹(PULL 模型的資料包通常劃分為 Header 資料包和 Body 資料包),能大大簡化資料包處理工作,但由於組件中間加了一個間接層,效率往往低於 PUSH模型。
更新記錄:
*** v2.2.1 更新 ***
> PULL 模型支援:
-----------------
- ISocketListener 增加 PULL 模型資料接收通知方法 OnReceive(dwConnID, int)
- 增加 PULL Socket 介面 IPullSocket,該介面的 Fetch(dwConnID, pBuffer, iLength) 方法用於抓取通訊資料
> Server:
-----------------
- 服務端 Socket 介面 ISocketServer 改名為 IServerSocket
- 增加 PULL Server Socket 監聽器抽象類別 CPullServerSocketListener
- 增加 PULL Server Socket 介面 IPullServerSocket
- 增加 PULL Server Socket 實作類別 CIocpPullServer
> Client:
-----------------
- 用戶端 Socket 介面 ISocketClient 改名為 IClientSocket
- 用戶端 Socket 實作類別 CSocketClient 改名為 CClientSocket
- 增加 PULL Client Socket 監聽器抽象類別 CPullClientSocketListener
- 增加 PULL Client Socket 介面 IPullClientSocket
- 增加 PULL Client Socket 實作類別 CPullClientSocket
> 其它更新:
-----------------
- 增加 PULL Socket 測試程式 TestEcho-Pull
- 在 SocketHelper.h (.cpp) 中添加若干協助結構體
> 升級說明:
-----------------
- 使用 HP-Socket v2.1.1 的應用程式可以安全升級到 v2.2.1
- 由於 ISocketServer、ISocketClient 和 CSocketClient 的名稱已修改,因此,應用程式需要對引用的名稱和包含的標頭檔名作相應修改
相關博文:
《高效能 Windows Socket 服務端與用戶端組件(原始碼及測試案例下載)》
《基於 IOCP 的通用非同步 Windows Socket TCP 高效能服務端組件的設計與實現》
《通用非同步 Windows Socket TCP 用戶端組件的設計與實現》
CodeProject