Socket開發框架之框架設計及分析

伍華聰發表於2016-03-22

雖然在APP應用、Web應用、Winform應用等大趨勢下,越來越多的企業趨向於這些應用系統開發,但是Socket的應用在某些場合是很必要的,如一些停車場終端裝置的接入,農業或者水利、壓力監測方面的裝置資料採集等,以及常見的IM(即時通訊,如騰訊QQ、阿里旺旺等)的客戶端,都可以採用Socket框架進行相關的資料採集和資訊通訊用途的,Socket應用可以做為APP應用、Web應用和Winform應用的補充。

1、Socket應用場景

一般情況下,客戶端和服務端進行Socket連線,需要進行資料的交換,也就是後臺提供資料查詢或者寫入的相關操作,它們的應用場景也是在後臺有一個應用資料庫支援的,如下所示。

Socket伺服器和客戶端的通訊原理如下所示,客戶端通過伺服器地址和埠發起Socket連線,伺服器在接收到Socket客戶端的請求後,開闢一個新的Socket連線進行通訊管理,兩方基於Socket協議進行資料的互動處理。

2、Socket框架設計思路

Socket開發是屬於通訊底層的開發,.NET本身也提供了非常豐富的類來實現Socket的開發工作,Socket框架應針對這些基礎功能進行了很好的封裝處理,已達到統一、高效的使用。

要掌握或者瞭解Socket開發,必須瞭解下面所述的場景及知識。

  • TCP客戶端,連線伺服器端,進行資料通訊
  • TCP伺服器端,負責偵聽客戶端連線
  • 連線客戶端的管理,如登陸,登出等,使用獨立執行緒處理
  • 資料接收管理,負責資料的接受,並處理佇列的分發,使用獨立執行緒處理,簡單處理後叫給“資料處理執行緒”
  • 資料處理執行緒,對特定的資料,採用獨立的執行緒進行資料處理
  • 資料的封包和解包,按照一定的協議進行資料的封裝和解包

針對以上內容,可以封裝以下功能的操作類作為共用基類:

  • BaseSocketClient,客戶端基類,負責客戶端的連結、斷開、傳送、接收等操作。
  • BaseSocketServer,TCP伺服器管理基類,負責在獨立的執行緒中偵聽指定的埠,如果有客戶端連線進來,則進行相應的處理。
  • BaseClientManager,連線客戶端管理類,該類主要負責客戶端登入超時處理,連線上來的客戶端維護,經過登陸驗證的客戶端維護,客戶端登陸驗證介面,客戶端傳送資料處理等功能。
  • BaseReceiver,資料接收處理類,該基類是所有接受資料的處理類,負責維護資料的佇列關係,並進一步進行處理。
  • ThreadHandler,資料獨立執行緒處理類,對每個不同型別的資料(不同的協議型別),可以用獨立的執行緒進行處理,這裡封裝了一個基類,用於進行資料獨立執行緒的處理。

1)Socket客戶端基類

我們知道Socket通訊,分為了客戶端和服務端,它們各自處理的事情是有所不同的,因此為了實現更好的程式碼重用,我們在這個基礎上進行了不同的封裝。針對Socket客戶端類,我們主要需要提供基礎的Socket連線及斷開、接收及傳送、封包拆包等常規操作過程,因此我們封裝了一個客戶端基類 BaseSocketClient。

但是為了基於不同的應用客戶端,實現不同的業務溝通,我們可以在服務端接收處理不同的客戶端,因此也就是需要對Socket客戶端進行派生擴充套件,例如本框架增加了一箇中心的Socket客戶端、分店的Socket客戶端、還有一個橋接的連線客戶端(可實現轉發資料功能)。

2)Socket服務端基類

相對於Socket客戶端基類,同樣我們也建立一個Socket服務端基類,通過繼承的方式,我們可以用於簡化程式碼的重複性。該服務端基類稱為TCP伺服器管理基類 BaseSocketServer,負責在獨立的執行緒中偵聽指定的埠,如果有客戶端連線進來,則進行相應的處理。

同樣我們也派生了兩個服務端的基類,方便對不同的Socket客戶端進行差異性處理,如對應上面的中心客戶端類ClientOfCall,我們增加一個對應的服務端類ServerForCall,其他的也類似,它們的繼承關係如下所示。

另外,由於我們允許不同的Socket客戶端類(如ClientOfCall、ClientOfShop)的接入,那麼在伺服器端也會有對應Socket服務端類(ServerForCall、ServerForShop)進行不同埠的偵聽,一旦在自己所屬埠有Socket接入,那麼服務端類會分派給不同Socket客戶端管理類來處理他們的關係和資料,這樣也就進一步引入一個客戶端管理類的概念,它對應不同的Socket客戶端。

這裡也根據需要定義了一個Socket客戶端管理基類BaseClientManager<T>,這個T代表對應不同的客戶端,這樣我們就可以派生出CallClientManager和ShopClientManager兩個不同的客戶端管理類了,它們的繼承關係如下所示。

3)資料接收處理基類

在不同的Socket客戶端連線到服務端後,服務端開闢一個新的執行緒進行對應的Socket資料通訊,那麼資料通訊這裡面的管理,我們可以為不同的Socket客戶端訂做一個對應的資料接收處理類,專門針對特定的Socket客戶端連線的資料進行處理。

這裡也根據需要定義了一個資料接收的基類BaseReceiver,同樣我們派生對應不同客戶端的資料接收類ReceivedForCall、ReceivedForShop和ReceivedForBridge等幾個具體的資料處理類,它們的繼承關係如下所示。

3、框架介面設計

1)引數配置

Socket伺服器需要一些引數來確定偵聽的IP地址、埠,以及資料庫的連線資訊,各種資料的處理時間間隔等引數,因此需要提供一個較好的管理介面來進行管理,本框架使用基於本地配置檔案的引數管理方式進行管理,引數介面如下所示。

客戶端也同樣需要配置一些引數,用來確定連線的伺服器IP及埠資訊,如下配置介面所示。

Socket伺服器監控介面,需要顯示一些基礎的狀態和Socket連線等基礎資訊,作為我們對整體狀態的瞭解,同時這些資訊可以記錄到日誌裡面供我們進行查閱和分析。

除了上面總體的設計外,其中還有一個地方需要細緻的展開來介紹,就是對Socket傳輸訊息的封裝和拆包,一般的Socket應用,多數採用基於順序位置和位元組長度的方式來確定相關的內容,這些處理對我們分析複雜的協議內容,簡直是一場災難,協議位置一旦變化或者需要特殊的處理,就是很容易出錯的,而且大多數程式碼充斥著很多位置的數值變數,分析和理解都是非常不便的。

如果對於整體的內容,使用一種比較靈活的訊息格式,如JSON格式,那麼我們可以很好的把訊息封裝和訊息拆包解析兩個部分,交給第三方的JSON解析器來進行,我們只需要關注具體的訊息處理邏輯就可以了,而且對於協議的擴充套件,就如JSON一樣,可以自由靈活,這樣瞬間,整個世界都會很清靜了。由於篇幅的原因,我將在下一個隨筆在進行介紹JSON格式的訊息處理過程。

除了上面的場景外,我們還需要考慮使用者訊息的加密和校驗等內容處理,這樣才能達到安全、完整的訊息處理,我們可以採用 RSA公鑰密碼系統。平臺通過傳送平臺RSA公鑰訊息向終端告知自己的RSA公鑰,終端回覆終端RSA公鑰訊息,反之亦然。這樣平臺和終端的訊息,就可以通過自身的私鑰加密,讓對方公鑰解密就可以了。

相關文章