SuperSocket 2.0應用1:基於固定頭協議的Socket服務器


SuperSocket:GitHubSuperSocket 2.0 中文文檔

本文開發環境:Win10 + VS2019 + .NetCore 3.1 + SuperSocket 2.0.0-beta.8。

Gitee:SuperSocketV2FixedHeaderSample

本文使用SuperSocket 2.0創建基於固定頭協議的Socket服務器,能夠滿足大部分自定義協議的服務器需求。本文使用協議如下所示,圍繞該協議說明PipelineFilter、PackageInfo、IAsyncCommand、AppSession、SuperSocketService等SuperSocket2.0元素是如何構建一個完整服務器的。

本文盡可能的將實現Socket服務器的類的作用說清楚,基本上就沒什么代碼了,具體可以參考Gitee相關項目。

0、准備工作

使用VS2019創建一個基於.NET Core的控制台程序,這里目標框架選擇了.NET Core 3.1。

使用NuGet工具搜索SuperSocket(需要勾選“包括預發行版”),選擇最新的版本(目前是2.0.0-beta.8)安裝。

在項目根目錄添加appsettings.json配置文件,並設置其文件屬性為“如果較新則復制”。(參考SuperSocket 2.0學習02:通過配置啟動 SuperSocket)。

1、PipelineFilter

SuperSocket 2.0使用PipelineFilter來處理應用層通信協議,其內置的FixedHeaderPipelineFilter實現了頭部格式固定並且包含內容長度的協議,從這個類繼承就能實現解析自己業務相關的固定頭協議處理類。

FixedHeaderPipelineFilter的構造函數需要傳入包頭大小,其余的包內容即為數據內容。根據我們的協議,包頭大小為4,因此將4傳入base類的構造函數即可。

其次是獲取數據長度,通過重載GetBodyLengthFromHeader實現。我們只需要在傳入的buffer中跳過2個字節,(以大端方式)讀取一個short類型數值即可,因為長度是2個字節。被我們跳過的字節很有用,會在解包時候保留該字節。

然后是通過重載DecodePackage解包,前面2個字節是類型,然后2個字節是數據長度,剩下的字節就是包體內容了。2個字節的類型,用於區分是什么命令,因此這里的類型和具體的命令就聯系起來了。

2、PackageInfo

前面解析了固定頭協議的數據包,就得有數據結構存放包數據,這就用到了PackageInfo。

PackageInfo需要作為PipelineFilter的泛型類型參數,以便在解包的時候能夠獲取對應包的對象。根據我們定義的協議,代表包類型的前2個字節是需要保存的,然后是包體字節。至於2個長度字節,則在進行包校驗的時候是必須保留的,否則就可以在PackageInfo類型中將其舍棄。

不得不說,僅僅如此是不能夠實現固定頭協議的命令映射的。SuperSocket2.0中的命令接口IAsyncCommand如果添加了Command標記,其泛型參數PackageInfo類型就必須實現IKeyedPackageInfo接口,以便將Command標記中的Key參數和IKeyedPackageInfo實例中的Key字段做映射。

我們的協議中Type是2個字節,因此將short類型作為IKeyedPackageInfo的泛型參數就再合適不過了,只是在解包的時候需要處理好大端小端的問題,以便獲取正確的short類型Key值。

3、IAsyncCommand

SuperSocket2.0中的命令類MyCommand需要實現IAsyncCommand接口(我們默認都是異步命令),在其ExecuteAsync方法中處理前面實現的PackageInfo對象。

要將MyCommand類和具體的Type進行綁定,需要在MyCommand類中添加Command屬性,標記其Key值為對應的協議即可。根據前面描述,其類型為short。如果Type為0xFF, 0xFE,那么MyCommand標記如下:

/// <summary>
/// 0xFF 0xFE
/// </summary>
[Command(Key = unchecked((short)(0xFF * 256 + 0xFE)))]
public class MyCommand : IAsyncCommand<MyPackageInfo>

這樣,MyCommand類就能將對應協議的Type類型對應起來,並在ExecuteAsync方法中對其進行業務處理。

4、AppSession

根據官方描述,AppSession代表一個和客戶端的邏輯連接,基於連接的操作應該定於在該類之中。你可以用該類的實例發送數據到客戶端,接收客戶端發送的數據或者關閉連接。

對於實現固定頭協議來說,AppSession不是必須的,但是站在應用服務器的角度來說,一個AppSession對象就是一個客戶端連接,該客戶端起碼會含有標識自己的信息,這是應用服務器所需要的。

AppSession是面向應用業務的類。

5、SuperSocketService

官方所述,SuperSocketService代表了監聽所有客戶端連接的服務器實例,宿主所有連接。應用程序級別的操作和業務邏輯可以定義在里面。

說白了,SuperSocketService就是實實在在的一個服務器對象,是應用級別的。在這個類中可以向用戶連接批量發送數據,比如進行一些事件監聽的客戶,在數據更新時候通過SuperSocketService可以跟注冊監聽的用戶同步。

但是SuperSocket2.0又支持多服務器實例,多服務器實例在.NET Core中是使用一個進程承載的,每個實例以HostedService的形式在進程(Host)中運行。如果要實現多進程或多服務器運行,需要使用Docker等容器技術。

6、Main函數

控制台程序的入口就是這里了,在這個函數中可以進行SuperSocket宿主的創建,命令、AppSession以及SuperSocketService的注入,配置日志等。總之,和.NET Core服務相關的配置都在這里進行。最后,宿主執行RunAsync方法就將Socket服務器啟動起來了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM