天天看點

輕量級的通信引擎 StriveEngine

如果對您的項目來說,太龐大、太重量級;如果您的項目不需要P2P、不需要傳檔案、不需要群集等功能,隻需要簡單的TCP/UDP通信。那麼,可以考慮使用輕量級的通信引擎StriveEngine。相比較而言,StriveEngine更單純、更容易上手,也更容易與已存在的遺留系統進行協作。 

一.StriveEngine 主要特性

1.底層采用高效的IOCP(完成端口)模型。

2.内部自動管理可複用的線程池、以及記憶體池。

3.内置多種通信引擎類型:TCP/UDP、文本協定/二進制協定、服務端/用戶端。而且,所有這些引擎的使用方式一緻。

4.解決了TCP通信中的粘包以及消息重組問題。

5.發送消息支援同步、異步兩種方式。

6.服務端引擎支援異步消息隊列模式。

7.用戶端TCP引擎支援斷線自動重連。

8.支援Sock5代理。

9.相容IPv6。 

二.StriveEngine與ESFramework/ESPlus/ESPlatform的差別

1.ESFramework 是一個功能強大的通信架構/平台,而StriveEngine是一個單純高效的通信引擎類庫。

2.ESFramework 更貼近應用層,而StriveEngine更貼近Socket層。

3.ESFramework 使用UserID标志每一個線上的用戶端,而StriveEngine則使用低階的IPEndPoint來标志每一個線上的用戶端。

4.可以認為StriveEngine就是ESFramework底層使用的核心。

5.ESFramework 定義了底層通信消息的格式(對ESFramework使用者是透明的),而StriveEngine對通信消息的格式未作任何定義。

6.ESFramework和StriveEngine都提供了服務端引擎和用戶端引擎。當涉及到要開發新的其它平台引擎來與ESFramework或StriveEngine協作時,比如:

(1)如果要開發其它平台的用戶端引擎與ESFramework的服務端引擎協作,則必需實作ESPlus協定格式;

(2)如果要開發其它平台的用戶端引擎與StriveEngine的服務端引擎協作,由于StriveEngine未定義任何消息格式,是以不存在要必需實作既有協定格式的問題。 

(3)與(2)同理,使用 StriveEngine的用戶端引擎,可以與任何其它現有的服務端協作。 

7.對于那些涉及到線上使用者管理、以UserID為中心的應用(比如即時通信應用),或者需要P2P通信、傳檔案等功能的應用來說,ESFramework更适合; 

  對于那些僅僅需要簡單而高效的通信功能的應用(如資料采集、消息轉發等)來說,StriveEngine更合适。  

三.StriveEngine 整體結構

StriveEngine内置了多種通信引擎,這些通信引擎都以接口的方式暴露了其功能,而不同的引擎卻都依據某些共通的部分,繼承了相同的基接口。  引擎接口的繼承關系如下所示:

輕量級的通信引擎 StriveEngine

INetworkEngine 是所有引擎的根接口,隻要是StriveEngine中的内置引擎,都實作了這個接口。

IServerEngine 是服務端引擎接口。IPassiveEngine 是用戶端引擎接口。

ITcpServerEngine 是基于TCP的服務端引擎接口。ITcpPassiveEngine是基于TCP的用戶端引擎接口。

IUdpEngine 是基于UDP的通信引擎接口。由于UDP是非連接配接協定,可以認為UDP通信的雙方是對等的,是以,服務端和用戶端都使用IUdpEngine即可。

ITextEngine 是基于文本協定的通信引擎的基接口。

下面,我們來詳細看看每個接口。

1.INetworkEngine

/// <summary>
    /// 所有網絡引擎(包括服務端引擎、用戶端引擎、TCP引擎、UDP引擎、二進制引擎、文本引擎)的基礎接口。    
    /// </summary>
    public interface INetworkEngine : IDisposable
    {      
        /// <summary>            
        /// 傳輸層協定類型,TCP或UDP
        /// </summary>
        ProtocolType ProtocolType { get; }        

        /// <summary>
        /// 引擎執行個體的建立時間。
        /// </summary>
        DateTime CreateTime { get; }

        /// <summary>
        /// 表示要監聽本地的哪個端口。如果設定其值小于等于0,則表示由系統自動配置設定。      
        /// 注意,引擎初始化完成後,不能再修改該屬性。
        /// </summary>
        int Port { get; set; }

        /// <summary>
        /// 對于服務端引擎,表示要綁定本地的哪個IP,如果設為null,則表示綁定本地所有IP。
        /// 對于用戶端引擎,表示要綁定本地的哪個IP與伺服器進行通信。如果設為null(其值會在初始化完成後被修改),則自動選擇位址清單中的某一個。
        /// 注意,引擎初始化完成後,不能再修改該屬性。
        /// </summary>
        string IPAddress { get; set; }

        /// <summary>
        /// 設定日志記錄的檔案路徑。如果設為null,表示不記錄日志。預設值為null。
        /// </summary>
        string LogFilePath { set; }

        /// <summary>
        /// Socket(網卡)發送緩沖區的大小。預設為8k。
        /// </summary>
        int SocketSendBuffSize { get; set; }

        /// <summary>
        /// Socket(網卡)接收緩沖區的大小。預設為8k。
        /// </summary>
        int SocketReceiveBuffSize { get; set; }

        /// <summary>
        /// 網絡引擎能夠接收的最大的消息尺寸。據此網絡引擎可以為每個Session/Connection開辟适當大小的接收緩沖區。
        /// 預設為1k。當接收到的消息尺寸超過MaxMessageSize時,将會關閉對應的連接配接(對TCP)或丢棄資料(對UDP)。
        /// </summary>
        int MaxMessageSize { get; set; }    

        /// <summary>
        /// 引擎執行個體是否已經被釋放。
        /// </summary>
        bool Disposed { get; }

        /// <summary>
        /// 初始化并啟動網絡引擎。如果修改了引擎配置參數,在應用新參數之前必須先重新調用該方法初始化引擎。
        /// </summary>
        void Initialize();      

        /// <summary>
        /// 當不再使用目前引擎執行個體時,釋放它。(異步方式)
        /// 注意:對于UDP或用戶端引擎,如果消息是同步處理的(HandleMessageAsynchronismly為false),請不要在消息處理器中調用Dispose方法,否則,會導緻死鎖。因為停止引擎要等到最後一條消息處理完畢才會傳回。
        /// 可以轉向調用異步的DisposeAsyn方法。
        /// </summary>
        void DisposeAsyn();

        /// <summary>
        /// 當引擎執行個體被釋放時,觸發此事件。
        /// </summary>
        event CbDelegate<INetworkEngine> EngineDisposed;

        /// <summary>
        /// 接收到一個完整的消息時觸發該事件。
        /// </summary>
        event CbDelegate<IPEndPoint,byte[]> MessageReceived;

        /// <summary>
        /// 将消息成功發送之後觸發該事件
        /// </summary>
        event CbDelegate<IPEndPoint, byte[]> MessageSent;       
    }

    /// <summary>
    /// 傳輸層協定類型。
    /// </summary>
    public enum ProtocolType
    {
        TCP = 0,
        UDP
    }

    /// <summary>
    /// 協定的格式。
    /// </summary>
    public enum ContractFormatStyle
    {
        /// <summary>
        /// 流協定或稱二進制協定。
        /// </summary>
        Stream = 0,
        /// <summary>
        /// 文本協定,如基于xml的。
        /// </summary>
        Text
    }      

(1)StriveEngine中的所有通信引擎在設定完必要的屬性後,都必須調用Initialize方法進行初始化,初始化完成後,引擎執行個體才開始正常工作。

(2)INetworkEngine從IDisposable繼承,表明通信引擎内部持有了重要的資源,當不再使用其執行個體時,要盡快調用IDisposable的Dispose方法釋放資源。

(3)當通信引擎被釋放後,會觸發EngineDisposed事件,并且此後,Disposed屬性将傳回true。

(4)請根據應用的需要謹慎地設定MaxMessageSize,如果設定的過大,可能會造成記憶體空間的浪費(特别是對于基于文本協定的服務端引擎)。

(5)通過MessageReceived事件,可以得到通信引擎接收到的所有消息;通過MessageSent事件,可以監控通信引擎發送出去的所有消息。 

2.IServerEngine

/// <summary>
    /// 服務端引擎接口。
    /// </summary>
    public interface IServerEngine : INetworkEngine
    {
        /// <summary>
        /// 到目标客戶的通道是否繁忙?
        /// </summary>
        bool ChannelIsBusy(IPEndPoint client);

        /// <summary>
        /// 給某個用戶端同步發資訊。注意:如果引擎已經停止或用戶端不線上,則直接傳回。   
        /// </summary>
        /// <param name="client">接收資料的用戶端</param>
        /// <param name="msg">消息</param>
        void SendMessageToClient(IPEndPoint client, byte[] msg);

        /// <summary>
        /// 給某個用戶端同步發資訊。注意:如果引擎已經停止或用戶端不線上,則直接傳回。   
        /// </summary>
        /// <param name="client">接收資料的用戶端</param>
        /// <param name="msg">消息</param>
        /// <param name="action">當通道繁忙時采取的動作:繼續發送或丢棄。</param>        
        void SendMessageToClient(IPEndPoint client, byte[] msg, ActionTypeOnChannelIsBusy action);

        /// <summary>
        /// 給某個用戶端異步發資訊。注意:如果引擎已經停止或用戶端不線上,則直接傳回。   
        /// </summary>
        /// <param name="client">接收資料的用戶端</param>
        /// <param name="msg">消息</param>    
        void PostMessageToClient(IPEndPoint client, byte[] msg);

        /// <summary>
        /// 給某個用戶端異步發資訊。注意:如果引擎已經停止或用戶端不線上,則直接傳回。   
        /// </summary>
        /// <param name="client">接收資料的用戶端</param>
        /// <param name="msg">消息</param>
        /// <param name="action">當通道繁忙時采取的動作:繼續發送或丢棄。</param>        
        void PostMessageToClient(IPEndPoint client, byte[] msg, ActionTypeOnChannelIsBusy action);
    }      

(1)SendMessageToClient和PostMessageToClient 分别表示同步和異步發送消息給用戶端。

(2)ChannelIsBusy 指的是在與目标用戶端的TCP連接配接上,是否有資料正在發送(服務端至用戶端)。

(3)ActionTypeOnChannelIsBusy 參數允許我們在通道繁忙時,丢棄不重要的消息。 

3.IPassiveEngine 

/// <summary>
    /// 用戶端引擎接口。
    /// </summary>
    public interface IPassiveEngine :INetworkEngine
    {
        /// <summary>
        /// 伺服器位址。
        /// </summary>
        AgileIPE ServerIPEndPoint { get; set; }   

        /// <summary>
        /// 發送消息的通道是否正忙。使用者可以根據該屬性決定是否要丢棄後續某些消息的發送。
        /// </summary>
        bool ChannelIsBusy { get; }     

        /// <summary>
        /// 将消息異步發送給伺服器,不經任何處理,直接發送。注意:如果引擎已經停止,則直接傳回。   
        /// </summary>
        /// <param name="msg">要發送的消息</param>
        /// <param name="action">當通道繁忙時采取的動作:繼續發送或丢棄。</param>
        void SendMessageToServer(byte[] msg, ActionTypeOnChannelIsBusy action);

        /// <summary>
        /// 将消息異步發送給伺服器,不經任何處理,直接發送。注意:如果引擎已經停止,則直接傳回。   
        /// </summary>
        /// <param name="msg">要發送的消息</param>       
        void SendMessageToServer(byte[] msg);

        /// <summary>
        /// 将消息同步發送給伺服器,不經任何處理,直接發送。注意:如果引擎已經停止,則直接傳回。   
        /// </summary>
        /// <param name="msg">要發送的消息</param>
        /// <param name="action">當通道繁忙時采取的動作:繼續發送或丢棄。</param>
        void PostMessageToServer(byte[] msg, ActionTypeOnChannelIsBusy action);

        /// <summary>
        /// 将消息同步發送給伺服器,不經任何處理,直接發送。注意:如果引擎已經停止,則直接傳回。   
        /// </summary>
        /// <param name="msg">要發送的消息</param>       
        void PostMessageToServer(byte[] msg);
    }      

(1)SendMessageToServer和PostMessageToServer 分别表示同步和異步發送消息給服務端。

(2)ChannelIsBusy 指的是目前與伺服器的TCP連接配接上,是否有資料正在發送(用戶端至服務端)。

(3)ActionTypeOnChannelIsBusy 參數允許我們在通道繁忙時,丢棄不重要的消息。  

4.ITcpServerEngine 

/// <summary>
    /// TCP服務端引擎接口。
    /// </summary>
    public interface ITcpServerEngine : IServerEngine
    {
        /// <summary>
        /// 引擎所采用的協定類型(二進制、文本)。
        /// </summary>
        ContractFormatStyle ContractFormatStyle { get; }

        /// <summary>
        /// 目前線上用戶端的數量。
        /// </summary>
        int ClientCount { get; }  

        /// <summary>
        /// 伺服器允許最大的同時線上用戶端數。
        /// </summary>
        int MaxClientCount { get;}       

        /// <summary>
        /// 給每個連接配接發送資料逾時時間(機關:毫秒。預設為-1,表示無限)。如果在指定的時間内未将資料發送完,則關閉對應的連接配接。       /// </summary>
        int WriteTimeoutInMSecs { get; set; }/// <summary>
        /// 每個通道連接配接上允許最大的等待發送【包括投遞】以及正在發送的消息個數。
        /// 當等待發送以及正在發送的消息個數超過該值時,将關閉對應的連接配接。如果設定為0,則表示不作限制。預設值為0。       /// </summary>
        int MaxChannelCacheSize { get; set; }     

        /// <summary>
        /// 監聽器是否開啟。
        /// </summary>
        bool IsListening { get; }

        /// <summary>
        /// 關閉到某個用戶端的連接配接,将觸發SomeOneDisconnected事件。
        /// </summary>     
        void CloseClient(IPEndPoint client);

        /// <summary>
        /// 關閉所有用戶端的連接配接。
        /// </summary>
        void CloseAllClient();

        /// <summary>
        /// 關閉或開啟監聽器。該方法調用不影響網絡引擎的消息接收和處理。
        /// </summary>      
        void ChangeListenerState(bool enabled);       

        /// <summary>
        /// 擷取所有線上連接配接的用戶端的位址。
        /// </summary>        
        List<IPEndPoint> GetClientList();

        /// <summary>
        /// 用戶端是否線上?
         /// </summary>        
        bool IsClientOnline(IPEndPoint client);

        /// <summary>
        /// 當某TCP連接配接斷開時,觸發該事件
        /// </summary>
        event CbDelegate<IPEndPoint> ClientDisconnected;

        /// <summary>
        /// 當某TCP連接配接建立成功時,觸發此事件。
        /// </summary>
        event CbDelegate<IPEndPoint> ClientConnected;

        /// <summary>
        /// 當tcp連接配接數量發生變化時,觸發此事件。
        /// </summary>
        event CbDelegate<int> ClientCountChanged;      

        /// <summary>
        /// 當連接配接監聽器的狀态發生變化時,觸發此事件。事件參數為true,表明連接配接監聽器啟動;事件參數為false,表明連接配接監聽器已停止。
        /// </summary>
        event CbDelegate<bool> ListenerStateChanged;
    }      

(1)WriteTimeoutInMSecs 用于設定發送資料的逾時。 最好給該屬性賦一個适當的值,因為在某些情況下,發送資料可能會導緻很長時間的阻塞。該屬性隻對同步發送有效。

(2)MaxChannelCacheSize 是服務端的一個安全設定。該設定用于防止伺服器為速度慢的通道緩存太多的消息,而導緻伺服器記憶體無限制增長。

(3)ChangeListenerState 用于改變伺服器的監聽狀态,其将觸發ListenerStateChanged事件,并改變IsListening屬性的值。

        如果IsListening為false,表示目前不接受新的TCP連接配接請求。 

(4)當有連接配接建立或斷開時,将分别觸發ClientConnected和ClientDisconnected事件。 

5.ITcpPassiveEngine

/// <summary>
    /// 用戶端TCP引擎接口。 
    /// </summary>
    public interface ITcpPassiveEngine :IPassiveEngine
    {
        /// <summary>
        /// 引擎所采用的協定類型(二進制、文本)。
        /// </summary>
        ContractFormatStyle ContractFormatStyle { get; }

        /// <summary>
        /// 當用戶端與伺服器的TCP連接配接斷開時,将觸發此事件。
         /// </summary>
        event CbDelegate ConnectionInterrupted;

        /// <summary>
        /// 自動重連開始時,觸發此事件。
        /// </summary>
        event CbDelegate ConnectionRebuildStart; 

        /// <summary>
        /// 自動重連成功後,觸發此事件。
        /// </summary>
        event CbDelegate ConnectionRebuildSucceed; 

        /// <summary>
        /// 自動重連超過最大重試次數時,表明重連失敗,将觸發此事件。
        /// </summary>
        event CbDelegate ConnectionRebuildFailure;

        /// <summary>
        /// Sock5代理伺服器資訊。如果不需要代理,則設定為null。
         /// </summary>
        Sock5ProxyInfo Sock5ProxyInfo { get; set; }       

        /// <summary>
        /// 目前是否處于連接配接狀态。
        /// </summary>
        bool Connected { get; }

        /// <summary>
        /// 當與伺服器斷開連接配接時,是否自動重連。
         /// </summary>
        bool AutoReconnect { get; set; }

        /// <summary>
        /// 當連接配接斷開時,自動重連嘗試的最大次數。預設值為int.MaxValue。
        /// </summary>
        int MaxRetryCount4AutoReconnect { get; set; }         

        /// <summary>
        /// 主動關閉與伺服器的連接配接。如果AutoReconnect為true,将引發自動重連。
         /// </summary>
        void CloseConnection();

        /// <summary>
        /// 手動重連。如果目前處于連接配接狀态,則直接傳回。
        /// </summary>
        /// <param name="retryCount">重試次數</param>
        /// <param name="retrySpanInMSecs">重試間隔時間,毫秒</param>
        void Reconnect(int retryCount, int retrySpanInMSecs);
    }      

(1)如果AutoReconnect設定為true,表示啟用自動重連,那麼,當連接配接斷開時,會按以下順序觸發相關事件: ConnectionInterrupted 、ConnectionRebuildStart 、   ConnectionRebuildSucceed/ConnectionRebuildFailure。

(2)注意,如果AutoReconnect設定為true,CloseConnection将會先關閉目前連接配接,然後再啟動自動重連。 

6.IUdpEngine 

/// <summary>
    /// Udp引擎基礎接口。
    /// </summary>
    public interface IUdpEngine  :INetworkEngine
    {       
        /// <summary>
        /// 向指定的端點發送UDP消息。注意:如果引擎已經停止,則直接傳回。
        /// </summary>
        /// <param name="message">要發送的消息</param>
        /// <param name="address">目标端點</param>           
        void SendMessage(IPEndPoint address, byte[] message);

        /// <summary>
        /// 向指定的端點投遞UDP消息。注意:如果引擎已經停止,則直接傳回。
        /// </summary>
        /// <param name="message">要投遞的消息</param>
        /// <param name="address">目标端點</param>           
        void PostMessage(IPEndPoint address, byte[] message);
    }      

UDP是非連接配接的協定,是以,UDP引擎不用區分用戶端和服務端,或者說,無論是用戶端還是服務端,都可以使用IUdpEngine。注意:IUdpEngine也從INetworkEngine繼承,是以,它具備了StriveEngine中基礎引擎所有的功能。 

四.如何使用StriveEngine

在StriveEngine中,我們不能直接new某個通信引擎的class來獲得其執行個體。StriveEngine提供了NetworkEngineFactory,我們可以通過工廠的靜态方法來得到通信引擎執行個體的引用。

1.通信引擎工廠

/// <summary>
    /// 通信引擎工廠。
    /// </summary>
    public static class NetworkEngineFactory
    {        
        /// <summary>
        /// 建立使用二進制協定的TCP服務端引擎。對于傳回的引擎執行個體,可以設定其更多屬性,然後調用其Initialize方法啟動引擎。
        /// </summary>
        /// <param name="port">服務端引擎監聽的端口号</param>
        /// <param name="helper">二進制協定助手接口</param>        
        public static ITcpServerEngine CreateStreamTcpServerEngine(int port, IStreamContractHelper helper);        

        /// <summary>
        /// 建立使用文本協定的TCP服務端引擎。對于傳回的引擎執行個體,可以設定其更多屬性,然後調用其Initialize方法啟動引擎。
        /// 注意:傳回的引擎執行個體,可以強轉為ITextEngine接口。
        /// </summary>
        /// <param name="port">服務端引擎監聽的端口号</param>
        /// <param name="helper">文本協定助手接口</param>  
        public static ITcpServerEngine CreateTextTcpServerEngine(int port, ITextContractHelper helper);       

        /// <summary>
        /// 建立使用二進制協定的TCP用戶端引擎。對于傳回的引擎執行個體,可以設定其更多屬性,然後調用其Initialize方法啟動引擎。
        /// </summary>        
        /// <param name="serverIP">要連接配接的伺服器的IP</param> 
        /// <param name="serverPort">要連接配接的伺服器的端口</param> 
        /// <param name="helper">二進制協定助手接口</param>        
        public static ITcpPassiveEngine CreateStreamTcpPassivEngine(string serverIP, int serverPort, IStreamContractHelper helper);    

        /// <summary>
        /// 建立使用文本協定的TCP用戶端引擎。對于傳回的引擎執行個體,可以設定其更多屬性,然後調用其Initialize方法啟動引擎。
        /// 注意:傳回的引擎執行個體,可以強轉為ITextEngine接口。
        /// </summary>
        /// <param name="serverIP">要連接配接的伺服器的IP</param> 
        /// <param name="serverPort">要連接配接的伺服器的端口</param> 
        /// <param name="helper">文本協定助手接口</param>  
        public static ITcpPassiveEngine CreateTextTcpPassiveEngine(string serverIP, int serverPort, ITextContractHelper helper);

        /// <summary>
        /// 建立UDP引擎。對于傳回的引擎執行個體,可以設定其更多屬性,然後調用其Initialize方法啟動引擎。
        /// </summary>       
        public static IUdpEngine CreateUdpEngine();
    }      

我們可以根據項目的需要(是TCP還是UDP、是文本協定還是二進制協定、是用于用戶端還是用于服務端),來調用NetworkEngineFactory的對應方法獲得正确的通信引擎執行個體。

注意:NetworkEngineFactory建立的所有通信引擎執行個體,必須要調用其Initialize方法後,引擎才算正常啟動。當然,在調用Initialize之前,可以根據需要設定其相關的屬性。

2.ContractHelper

StriveEngine内部通過ContractHelper來從接收的網絡流中識别完整的消息,針對消息格式為文本和二進制,ContractHelper就劃分為對應的ITextContractHelper 和IStreamContractHelper。我們看到,在通過NetworkEngineFactory建立通信引擎執行個體時,其有個參數是必須傳入ContractHelper引用的。是以,在項目中,我們必須實作ITextContractHelper或者是IStreamContractHelper。

(1) ITextContractHelper  

/// <summary>
    /// 文本協定助手接口。
    /// </summary>
    public interface ITextContractHelper 
    {
        /// <summary>
        /// 消息的結束辨別符(經過編碼後得到的位元組數組)。
        /// </summary>
        byte[] EndToken { get; }     
    }      

當使用文本協定時,通常,使用某一個或多個特殊的字元作為消息的結束符(EndToken)。ITextContractHelper的EndToken是一個byte[],其指的是消息的結束符經過編碼(比如UTF-8)後得到的位元組數組。通信引擎即通過ITextContractHelper提供的EndToken來從網絡流中識别完整的消息。 

如果是使用UTF-8對文本消息(當然,也包括消息結束符)進行編解碼,則可以使用StriveEngine内置的DefaultTextContractHelper,其實,它的實作非常簡單: 

/// <summary>
    /// StriveEngine内置的ITextContractHelper實作。使用UTF-8對EndToken進行編碼。
    /// </summary>
    public class DefaultTextContractHelper : ITextContractHelper
    {        
        public DefaultTextContractHelper(string endTokenStr)
        {
            this.endToken = System.Text.Encoding.UTF8.GetBytes(endTokenStr);
        }

        private byte[] endToken;
        public byte[] EndToken
        {
            get
            {
                return this.endToken;
            }
        }
    }      

(2)IStreamContractHelper  

/// <summary>
    /// 二進制協定助手接口。
    /// </summary>
    public interface IStreamContractHelper
    {
        /// <summary>
        /// 從消息頭中解析出消息體的長度。
        /// </summary>
        /// <param name="head">完整的消息頭,長度固定為MessageHeaderLength</param>
        /// <returns>消息體的長度</returns>
        int ParseMessageBodyLength(byte[] head);

        /// <summary>
        /// 消息頭的長度。
        /// </summary>
        int MessageHeaderLength { get; }
    }      

當使用二進制協定時,通常,消息分為消息頭(Header)和消息體(Body)兩部分,消息頭是必須的,而消息體可以為null。消息頭的長度是固定的(比如8個位元組),且其至少包含了一個字段--消息體的長度(或根據消息頭的内容可以間接結算出消息體的長度)。

3.使用StriveEngine的步驟

(1)實作ITextContractHelper或者是IStreamContractHelper接口。

(2)調用NetworkEngineFactory的建立引擎的方法,得到正确的通信引擎執行個體。

(3)根據需要,設定引擎執行個體的某些屬性(如MaxMessageSize屬性)。

(4)根據需要,預定引擎執行個體的某些事件(如MessageReceived事件)。

(5)調用引擎執行個體的Initialize方法啟動通信引擎。 

五.Demo下載下傳

通過上述的内容大緻了解了StriveEngine後,接下來我們通過一個簡單的demo來看看在實際項目中是如何使用StriveEngine的。

該Demo是一個簡單的用戶端與服務端進行消息通信的demo,消息使用文本協定。該Demo總共包括三個項目:

(1)StriveEngine.SimpleDemoServer:基于StriveEngine開發的服務端。

(2)StriveEngine.SimpleDemoClient:基于StriveEngine開發的用戶端。

(3)StriveEngine.SimpleDemo:直接基于.NET的Socket開發的用戶端,其目的是為了示範:在用戶端不使用StriveEngine的情況下,如何與基于StriveEngine的服務端進行通信。

Demo運作起來後的截圖如下所示:

輕量級的通信引擎 StriveEngine

繼續閱讀