天天看點

通用異步 Windows Socket TCP 用戶端元件的設計與實作

最重要的第一個問題:如何才能達到通用?

  答:很簡單。

    1、限制元件的職能,說白了,通信元件的唯一職責就是接受和發送位元組流,絕對不能參與上層協定解析等工作。不在其位不謀其政就是這個意思。

最重要的第二個問題:可用性如何,也就是說使用起來是否是否友善?

  答:這個問題問得很好,可用性對所有通用元件都是至關重要的,如果太難用還不如自己重頭寫一個來得友善。是以,ISocketClient 和 IClientSocketListener 接口設計得盡量簡單易用(通俗來說就是“傻瓜化”),這兩個接口的主要方法均不超過 5 個。

最重要的第三個問題:元件的性能如何?

  作為底層的通用元件,性能問題是必須考慮的,絕對不能成為系統的瓶頸。而另一方面,從實際出發,畢竟隻是一個用戶端元件,它的并發性要求遠沒有服務端那麼高。是以,元件在設計上充分考慮了性能、現實使用情景、可用性和實作複雜性等因素,確定滿足性能要求的同時又不會寫得太複雜。做出以下兩點設計決策:

在單獨線程中實作 Socket 通信互動。這樣可以避免與主線程或其他線程互相幹擾。

I/O 模型選擇 WSAEventSelect。細說一下選擇這種 I/O 模型的原因:(各種 I/O 模型的性能比較可以參考:《Windows 網絡程式設計(中文第二版)》第 154 頁)

阻塞模型:(不解析,你懂的^_^)

非阻塞模型:(性能太低)

WSAAsyncSelect: (兩個原因:a、性能太低;b、對于純 Console 程式還要背負 HWND 實在是傷不起呀!)

重疊 I/O:(有點複雜了)

完成端口:(何必呢?)

  唉,理論的東西就先别吹那麼多了,直接上代碼吧,求你了 !!

  OK!先看看 ISocketClient 和 IClientSocketListener 的接口定義:

通用異步 Windows Socket TCP 用戶端元件的設計與實作
通用異步 Windows Socket TCP 用戶端元件的設計與實作

  

  ISocketClient 接口主要有以下三個方法:

Start():啟動通信

Send():發送資料

Stop():停止通信

  IClientSocketListener 接口有以下五個通知方法:

OnConnect()

OnSend()

OnReceive()

OnClose()

OnError() 

   夠簡單了吧^_^,使用者隻需通過三個方法操作元件,然後處理五個元件通知。下面我們再看看元件的具體實作,先看元件類定義:

通用異步 Windows Socket TCP 用戶端元件的設計與實作
通用異步 Windows Socket TCP 用戶端元件的設計與實作

  從上面的定義可以看出,元件實作類本身并沒有提供額外的公共方法,它完全是可以被替換的。元件在構造函數中接收監聽器對象,并且儲存為其成員屬性,是以可以在需要的時候向監聽器發送事件通知。

  另外,不知各位看官是否注意到一個奇怪的成員屬性:“CInitSocket m_wsSocket; ”,這個屬性在其它地方從來都不會用到,那麼它是幹嘛的呢?在回答這個問題之前,首先想問問大家:Windows Socket 操作的整個操作過程中,第一個以及最後一個被調用的方法是什麼?是 socket()、connect()、bind()、還是 closesocket() 嗎?都錯!答案是 —— ::WSAStartup() 和 ::WSACleanup()。每個程式都要調用一下這兩個方法确實是很煩的,又不雅觀。 其實,m_wsSocket 的唯一目的就是為了避免手工調用者兩個方法,看看它的定義就明白了:

通用異步 Windows Socket TCP 用戶端元件的設計與實作
通用異步 Windows Socket TCP 用戶端元件的設計與實作

   現在我們看看元件類實作檔案中幾個重要方法的定義:

通用異步 Windows Socket TCP 用戶端元件的設計與實作
通用異步 Windows Socket TCP 用戶端元件的設計與實作

  從上面的代碼可以看出:通信過程中,元件的使用者不需要對通信過程進行任何幹預,整個底層通信過程對使用者來說是透明的,使用隻需集中精力處理好幾個元件通知。下面來看看元件的一個使用示例:

通用異步 Windows Socket TCP 用戶端元件的設計與實作
通用異步 Windows Socket TCP 用戶端元件的設計與實作
通用異步 Windows Socket TCP 用戶端元件的設計與實作
通用異步 Windows Socket TCP 用戶端元件的設計與實作

  好了,碼了一個晚上的字,累啊!到此為止吧,感謝收看~

繼續閱讀