天天看點

AgileEAS.NET SOA 中間件平台.Net Socket通信架構-介紹

一、前言

     AgileEAS.NET SOA 中間件平台是一款基于基于靈活并行開發思想和Microsoft .Net構件(元件)開發技術而建構的一個快速開發應用平台。用于幫助中小型軟體企業建立一條适合市場快速變化的開發團隊,以達到節省開發成本、縮短開發時間,快速适應市場變化的目的。

     AgileEAS.NET SOA中間件平台提供了靈活快速開發軟體工程的最佳實踐,通過提供大量的基礎支撐功能如IOC、ORM、SOA、分布式體系及靈活并發開發方法所支撐的插件開發體系,以及提供了大量的實體、資料模型設計生成工具、代碼生成工具,用于幫助中小軟體開發商快速成長。

AgileEAS.NET SOA 中間件平台.Net Socket通信架構-介紹

     AgileEAS.NET平台充分把握目前軟體行業快速發展的新趨勢,基于靈活并行開發、快速适應市場這樣淳樸的軟體工程實踐,采用業界廣泛使用的Microsoft .Net構件(元件)開發技術實踐了這種開發思想,幫助軟體企業實作“靈活變化、快速适合”的目标,進而幫助軟體企業在激烈的市場競争中赢得先機并獲得更高的回報。

二、關于Socket/Tcp架構的需求

     在AgileEAS.NET SOA 中間件平台在大量客戶的使用過程之中,有的客戶提出了一些基于“消息推”、和應用系統事件通知的需求,比如在“醫院資訊系統”、“電子病曆系統‘、”區域公共衛生平台“、等系統之中就提供了這樣的需求,比如當大夫為病人開立了醫囑之後、需要在相關護理人員即時提示,之前大家都使用資料庫重新整理,資料庫的壓力都比較大,是以迫切的提出了這樣的需求。

     另外一個原因是AgileEAS.NET SOA 中間件平台之前一直使用WCF、WS、Romotinig通信做為SOA分布式架構的通信基礎,我們在考慮WS、WCF的某些協定并不能提供給我們非常高效的通信,是以我們也需要有一套直接基于Socket/TCP的通信體系用于支撐我們的SOA分布式服務業務體系。

三、AgileEAS.NET SOA 中間件Socket/Tcp架構結構

     AgileEAS.NET SOA中間件需要的Socket/Tcp架構嚴格意思是需要的基于Socket的通信消息中件間,其所提供的功能本質是對消息的處理,是以其所提供的API有三大類、Socket架構本身、消息架構及消息處理架構,以下是AgileEAS.NET SOA中間件的Socket/Tcp的應用架構結構:

AgileEAS.NET SOA 中間件平台.Net Socket通信架構-介紹

     各上圖我們可以看到AgileEAS.NET SOA中間件需要的Socket/Tcp架構實作了這麼一件有意思的事,把原生的Socekt基于資料流的流式通信模式轉換為基于消息的消息通信模式,讓開發人員多複雜的系統Socket通信和資料流處理之中解放出來,轉而關心高層通信消息的設計和消息處理的業務設計與實作。

三、AgileEAS.NET SOA 中間件Socket/Tcp架構重要的接口和類

AgileEAS.NET SOA 中間件平台.Net Socket通信架構-介紹

     其中ISocketCient接口為客戶段功能封裝,其定義大體如下:

1: /// <summary>      
2: /// Tcp用戶端接口。      
3: /// </summary>      
4: public interface ISocketClient : ISocketEngine      
5: {      
6:     /// <summary>      
7:     /// 用戶端狀态。      
8:     /// </summary>      
9:     ClientState ClientState      
10:     {      
11:         get;      
12:     }              
13:        
14:     /// <summary>      
15:     /// 連接配接Tcp伺服器。      
16:     /// </summary>      
17:     bool Connect();      
18:        
19:     /// <summary>      
20:     /// 關閉與伺服器的連接配接。      
21:     /// </summary>      
22:     void Close();      
23:        
24:     /// <summary>      
25:     /// 發送消息。      
26:     /// </summary>      
27:     /// <param name="message">消息。</param>      
28:     void Send(IMessage message);      
29:        
30:     /// <summary>      
31:     /// 調用消息,用于伺服器/用戶端應用中的請示==》響應消息的應用。      
32:     /// </summary>      
33:     /// <param name="request">請示消息。</param>      
34:     /// <returns>伺服器傳回的響應消息。</returns>      
35:     IMessage Invoke(IMessage request);      
36:        
37:     /// <summary>      
38:     /// 異步調用消息,用于伺服器/用戶端應用中的請示==》響應消息的應用。      
39:     /// </summary>      
40:     /// <param name="request">請示消息。</param>      
41:     /// <returns>包含響應消息的異步任務。</returns>      
42:     NetInvokeTask BeginInvoke(IMessage request);      
43:        
44:     /// <summary>      
45:     /// 伺服器發生錯誤時觸發。      
46:     /// </summary>      
47:     event ErrorEventHandler Error;      
48:        
49:     /// <summary>      
50:     /// 連接配接伺服器後觸發。      
51:     /// </summary>      
52:     event EventHandler Connected;      
53:        
54:     /// <summary>      
55:     /// 斷開伺服器連接配接後觸發。      
56:     /// </summary>      
57:     event EventHandler Closed;      
58: }      

     其是最重要方法為void Send(IMessage message)方法,即發送一個消息到伺服器,這個方法也是對使用者開放的最重要方法,在這裡發送的不是位元組流,而是一個實作了IMessage接口的消息對象,當服戶段接收到IMessage對象之後會調用與其對應的消息處理器(IMessageHandler)對象進行消息處理,反之客戶段收到IMessage也會調用與其相關的消息處理器(IMessageHandler)對象進行處理。

     ISocketServer、ISocketServerBase接口:

1: /// <summary>      
2: /// Socket伺服器基類接口。      
3: /// </summary>      
4: public interface ISocketServerBase : ISocketEngine      
5: {      
6:     /// <summary>      
7:     /// 用戶端會話集合。      
8:     /// </summary>      
9:     IList<NetSession> Sessions      
10:     {      
11:         get;      
12:     }      
13:        
14:     /// <summary>      
15:     /// 注冊了一個新會話後發生。      
16:     /// </summary>      
17:     event NetSessionEventHandler SessionStarted;      
18:        
19:     /// <summary>      
20:     /// 某一個會話結束後發生。      
21:     /// </summary>      
22:     event NetSessionEventHandler SessionAbandoned;      
23:        
24:     /// <summary>      
25:     /// 發送消息。      
26:     /// </summary>      
27:     /// <param name="target">消息接收方ID(會話ID)。</param>      
28:     /// <param name="message">消息。</param>      
29:     void Send(Guid target, IMessage message);      
30:        
31:     /// <summary>      
32:     /// 發送網絡消息。      
33:     /// </summary>      
34:     /// <param name="target">消息接收方ID(會話ID)。</param>      
35:     /// <param name="netMessage">網絡消息。</param>      
36:     void Send(Guid target, NetMessage netMessage);      
37:        
38:     /// <summary>      
39:     /// 發送網絡封包(僅網關模式有效)。      
40:     /// </summary>      
41:     /// <param name="target">消息接收方ID(會話ID)。</param>      
42:     /// <param name="netPacket">網絡封包。</param>      
43:     void Send(Guid target, NetPacket netPacket);      
44:        
45:     /// <summary>      
46:     /// 發送網絡資料(僅網關模式有效)。      
47:     /// </summary>      
48:     /// <param name="target">消息接收方ID(會話ID)。</param>      
49:     /// <param name="buffer">網絡資料。</param>      
50:     void Send(Guid target, byte[] buffer);      
51: }      
1: /// <summary>      
2: /// Socket伺服器接口。      
3: /// </summary>      
4: public interface ISocketServer :  ISocketServerBase      
5: {      
6:     /// <summary>      
7:     /// 用戶端連接配接數。      
8:     /// </summary>      
9:     int ClientCount      
10:     {      
11:         get;      
12:     }      
13:        
14:     /// <summary>      
15:     /// 伺服器狀态。      
16:     /// </summary>      
17:     ServerState ServerState      
18:     {      
19:         get;      
20:     }              
21:        
22:     /// <summary>      
23:     /// 開始Tcp伺服器。      
24:     /// </summary>      
25:     void StartServer();      
26:        
27:     /// <summary>      
28:     /// 停止Tcp伺服器。      
29:     /// </summary>      
30:     void StopServer();      
31:        
32:     /// <summary>      
33:     /// 關閉指定客戶的連接配接。      
34:     /// </summary>      
35:     /// <param name="client">客戶Guid。</param>      
36:     void AbandonSession(System.Guid client);      
37:        
38:     /// <summary>      
39:     /// 伺服器發生錯誤時觸發。      
40:     /// </summary>      
41:     event ServerErrorEventHandler ServerError;      
42:        
43:     /// <summary>      
44:     /// 伺服器啟動後觸發。      
45:     /// </summary>      
46:     event System.EventHandler ServerStarted;              
47:        
48:     /// <summary>      
49:     /// 伺服器停止後觸發。      
50:     /// </summary>      
51:     event System.EventHandler ServerStopped;      
52: }      

     這兩個接口定義了SocketServer的一些行為和屬性,其中最重要的方法還是void Send(Guid target, IMessage message),實作向某個特定客戶段連接配接發送應用消息,别外定義了一個IList<NetSession> Sessions屬性,表示目前連接配接到此SocketServer的所有用戶端會話資訊。

     NetSession表示伺服器的一個客戶段連接配接會話,包括連接配接上下文資訊和連接配接的Socket通信對象,當某個SocketClient發送給SocketServer的資訊都會被與其應對的NetSession進行處理,NetSession定義兩個重要的方法public void Reply(uint requestID, IMessage message)和public void Abandon(),其中Reply表示向用戶端回複一個消息,Abandon表示伺服器強制中止此會話。

     在整個Socket/tcp架構之中進行通信的最基本單元都是IMessage,那麼SocketClient、SocketServer接收到IMessage如何處理呢,答案是由與之配對的IMessageHandler進行處理,是以SocketClient、SocketServer都實作了一個基礎接口ISocketEngine:

1: /// <summary>      
2: /// Socket引擎,Socket網絡通信基礎類。      
3: /// </summary>      
4: public interface ISocketEngine : IDisposable      
5: {      
6:     /// <summary>      
7:     /// 通信引擎的全局唯一辨別符号。      
8:     /// </summary>      
9:     System.Guid Guid      
10:     {      
11:         get;      
12:     }      
13:        
14:     /// <summary>      
15:     /// IP位址和端口号。      
16:     /// </summary>      
17:     IPEndPoint IPEndPoint      
18:     {      
19:         get;      
20:         set;      
21:     }      
22:        
23:     /// <summary>      
24:     /// IP位址。      
25:     /// </summary>      
26:     string IPAddress      
27:     {      
28:         get;      
29:         set;      
30:     }      
31:        
32:     /// <summary>      
33:     /// 端口号。      
34:     /// </summary>      
35:     int Port      
36:     {      
37:         get;      
38:         set;      
39:     }      
40:        
41:     /// <summary>      
42:     /// 封包最大長度。      
43:     /// </summary>      
44:     int MessageMaxSize      
45:     {      
46:         get;      
47:     }              
48:        
49:     /// <summary>      
50:     /// 注冊消息處理器。      
51:     /// </summary>      
52:     /// <typeparam name="T">消息類型。</typeparam>      
53:     /// <param name="hander">消息處理器。</param>      
54:     void AddHander<T>(IMessageHandler<T> hander) where T : IMessage;      
55:        
56:     /// <summary>      
57:     /// 通過Socket發送資料之後觸發。      
58:     /// </summary>      
59:     event SocketDataHandler SocketDataSend;      
60:        
61:     /// <summary>      
62:     ///  通過Socket接收資料之後觸發。      
63:     /// </summary>      
64:     event SocketDataHandler SocketDataReceived;      
65:        
66:     /// <summary>      
67:     /// 發送封包完成之後觸發。      
68:     /// </summary>      
69:     event PacketHandler PacketSend;      
70:        
71:     /// <summary>      
72:     /// 封包接收完成之後觸發。      
73:     /// </summary>      
74:     event PacketHandler PacketReceived;      
75:        
76:     /// <summary>      
77:     /// 載送完一個NetMessage之後觸發。      
78:     /// </summary>      
79:     event NetMessageHandler NetMessageSend;      
80:        
81:     /// <summary>      
82:     /// 接收完一個NetMessage之後觸發。      
83:     /// </summary>      
84:     event NetMessageHandler NetMessageReceived;      
85:        
86:     /// <summary>      
87:     /// 消息發送完成之後觸發。      
88:     /// </summary>      
89:     event MessageHandler MessageSend;      
90:        
91:     /// <summary>      
92:     /// 接收消息完成之後觸發。      
93:     /// </summary>      
94:     event MessageHandler MessageReceived;      
95: }      

     其中方法void AddHander<T>(IMessageHandler<T> hander) where T : IMessage實作對消息處理器的注冊,以便收到IMessage之後選擇合适的處理器進行處理。

四、消息和消息處理器

     從以上的介紹我們可以明确的知道AgileEAS.NET SOA中間件Socket/Tcp架構是的一個基于消息對象的消息通信架構,那麼其最核心的業務就是定義消息及消息的處理思路,我們稱之為消息及消息處理器結構:

AgileEAS.NET SOA 中間件平台.Net Socket通信架構-介紹

     其中IMessage接口為Socket/Tcp架構中最重要的接口,所有高層的應用消息都需要實作本接口:

1: /// <summary>      
2: /// 消息接口定義。      
3: /// </summary>      
4: /// <remarks>      
5: /// 這裡所說的消息是指業務處理的最小單元,而不是傳輸于網絡之間的網絡消息。      
6: /// </remarks>      
7: public interface IMessage      
8: {      
9:     /// <summary>      
10:     /// 從指定的 MessageReader加載消息對象。      
11:     /// </summary>      
12:     /// <param name="reader">消息讀取器。</param>      
13:     void Load(BufferReader reader);      
14:        
15:     /// <summary>      
16:     /// 将消息對象儲存到指定的MessageWriter。      
17:     /// </summary>      
18:     /// <param name="writer">消息編寫器。</param>      
19:     void WriteTo(BufferWriter writer);      
20: }      

     其中Load和WriteTo實作IMessage消息對象執行個體與位元組流之間進行互相轉換,Load消息用于從位元組流之中讀取并執行個體化消息、WriteTo把消息轉換為流寫入消息流之中,在應用開發過程之中必須實作這兩個方法并且在消息類上打上MessageAttribute标記:

1: /// <summary>      
2: /// 消息ID屬性。      
3: /// </summary>      
4: /// <remarks>      
5: /// 标記網絡消息,确定其唯一的ID。      
6: /// </remarks>      
7: [AttributeUsage(AttributeTargets.Class)]      
8: public class MessageAttribute : Attribute      
9: {      
10:     /// <summary>      
11:     /// 初始化MessageAttribute對象執行個體。      
12:     /// </summary>      
13:     /// <param name="messageID">消息ID。</param>      
14:     public MessageAttribute(string messageID)      
15:         :this(messageID,string.Empty)      
16:     {      
17:        
18:     }      
19:        
20:     /// <summary>      
21:     /// 初始化MessageAttribute對象執行個體。      
22:     /// </summary>      
23:     /// <param name="messageID">消息ID。</param>      
24:     /// <param name="description">消息說明。</param>      
25:     public MessageAttribute(string messageID, string description)      
26:     {      
27:         this.MessageID = new Guid(messageID);      
28:         this.Description = description;      
29:     }      
30:        
31:     /// <summary>      
32:     /// 消息ID。      
33:     /// </summary>      
34:     public Guid MessageID      
35:     {      
36:         get;      
37:         set;      
38:     }      
39:        
40:     /// <summary>      
41:     /// 消息說明。      
42:     /// </summary>      
43:     public string Description      
44:     {      
45:         get;      
46:         set;      
47:     }      
48: }      

     MessageAttribute标記用于向已實作IMessage接口的具體消息的消息ID與消息說明,即向Socket通信架構聲音本消息的唯一性之用,其中MessageID為一個GUID對象,GUID對象理論上是唯一的,我們可以表示消息的唯一性,以下是一個具體的消息例子:

1: /// <summary>      
2: /// 使用者登入消息。      
3: /// </summary>      
4: [Message("F42433DF-2D4D-4514-9523-2FE911E63CAA", "登入消息")]      
5: [Serializable]      
6: public class LoginMessage : IMessage      
7: {      
8:     /// <summary>      
9:     /// 使用者名。      
10:     /// </summary>      
11:     public string LoginID      
12:     {      
13:         get;      
14:         set;      
15:     }      
16:        
17:     /// <summary>      
18:     /// 密碼。      
19:     /// </summary>      
20:     public string PassWord      
21:     {      
22:         get;      
23:         set;      
24:     }      
25:        
26:     #region IMessage 成員      
27:        
28:     /// <summary>      
29:     ///       
30:     /// </summary>      
31:     /// <param name="reader"></param>      
32:     public void Load(EAS.IO.BufferReader reader)      
33:     {      
34:         LoginID = reader.ReadString();      
35:         PassWord = reader.ReadString();      
36:     }      
37:        
38:     /// <summary>      
39:     ///       
40:     /// </summary>      
41:     /// <param name="writer"></param>      
42:     public void WriteTo(EAS.IO.BufferWriter writer)      
43:     {      
44:         writer.Write(LoginID);      
45:         writer.Write(PassWord);      
46:     }      
47:        
48:     #endregion      
49: }      

     以上是一個具體消息的例子,其表明消息ID為“F42433DF-2D4D-4514-9523-2FE911E63CAA”,其作用是登入消息,用于實作類似登入業務。

五、可靠的消息中間件

     AgileEAS.NET SOA中間件Socket/Tcp架構是一個可靠的消息中間件,在設計過程之初就選擇了完成端口模型進行開發,以保證服務的高并發和吞吐量,在底層消息通信上,我們選擇了不超過8K的可變大小通信封包,比如當一個高層的IMeesage隻有512位元組内容的時候,會取轉成一個一個遠小于8K的封包進行發送,如果一個高層IMeesage為66K時,會被分解成為9條消息封包進行通信,前8條消息封包長度為8K,最後一條不滿足8K,接收文收到這9條封包後組合并轉換為IMeesage對象之後交由消息處理器IMeeesgaHandler進行處理。

     在進行消息封包收發過程之中,經過長期測試、驗證、設計和選擇了高性能的防粘包設計,避免應用開發者頭疼的消息粘包問題。

六、AgileEAS.NET SOA中間件需要的Socket/Tcp架構下載下傳

     AgileEAS.NET SOA中間件Socket/Tcp架構包含在AgileEAS.NET SOA中間件平台之中,具體定義在EAS.MicroKernel.dll程式集之中,要使用AgileEAS.NET SOA中間件Socket/Tcp架構進行基于Socket的通信開發,請通過AgilleEAS.NET SOA 中站件平台官方網站的最新下載下傳頁面下載下傳。

七、聯系我們

     為了完善、改進和推廣AgileEAS.NET而成立了靈活軟體工程實驗室,是一家研究、推廣和發展新技術,并緻力于提供具有自主知識産權的業務基礎平台軟體,以及基于業務基礎平台了開發的管理軟體的專業軟體提供商。主要業務是為客戶提供軟體企業研發管了解決方案、企業管理軟體開發,以及相關的技術支援,管理及技術咨詢與教育訓練業務。

     AgileEAS.NET平台自2004年秋呱呱落地一來,我就一直在逐漸完善和改進,也被應用于保險、醫療、電子商務、房地産、鐵路、教育等多個應用,但一直都是以我個人在推廣,2010年因為我辭職休息,我就想到把AgileEAS.NET推向市場,讓更多的人使用。

     我的技術團隊成員都是合作多年的老朋友,因為這個平台是免費的,是以也沒有什麼收入,都是由程式員的那種理想與信念堅持,在此我感謝一起奮鬥的朋友。

團隊網站:http://www.agilelab.cn

AgileEAS.NET網站:http://www.agileeas.net

官方部落格:http://eastjade.cnblogs.com

github:https://github.com/agilelab/eas

QQ:47920381

AgileEAS.NET QQ群:

113723486(AgileEAS SOA 平台)/上限1000人

199463175(AgileEAS SOA 交流)/上限1000人

120661978(AgileEAS.NET 平台交流)/上限1000人

212867943(AgileEAS.NET研究)/上限500人

147168308(AgileEAS.NET應用)/上限500人

172060626(深度AgileEAS.NET平台)/上限500人

116773358(AgileEAS.NET 平台)/上限500人

125643764(AgileEAS.NET探讨)/上限500人

193486983(AgileEAS.NET 平台)/上限500人

郵件:[email protected],[email protected],

電話:18629261335。

作者:魏瓊東

出處:http://www.cnblogs.com/eastjade

關于作者:有13年的軟體從業經曆,專注于中小軟體企業軟體開發過程研究,通過在技術與管理幫助中小軟體企業實作技術層面開源節流的目的。熟悉需求分析、企業架構、項目管理。現主要從事基于AgileEAS.NET平台的技術咨詢工作,主要服務于醫療衛生、鐵路、電信、物流、物聯網、制造、零售等行業。如有問題或建議,請多多賜教!

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,如有問題,可以通過[email protected] 聯系我,也可以加入QQ群:113723486、199463175、116773358、116773358、212867943、147168308、59827496、193486983、15118502和大家共同讨論,非常感謝。

繼續閱讀