AgileEAS.NET SOA 中介軟體平臺.Net Socket通訊框架-介紹
一、前言
AgileEAS.NET SOA 中介軟體平臺是一款基於基於敏捷並行開發思想和Microsoft .Net構件(元件)開發技術而構建的一個快速開發應用平臺。用於幫助中小型軟體企業建立一條適合市場快速變化的開發團隊,以達到節省開發成本、縮短開發時間,快速適應市場變化的目的。
AgileEAS.NET SOA中介軟體平臺提供了敏捷快速開發軟體工程的最佳實踐,通過提供大量的基礎支撐功能如IOC、ORM、SOA、分散式體系及敏捷併發開發方法所支撐的外掛開發體系,以及提供了大量的實體、資料模型設計生成工具、程式碼生成工具,用於幫助中小軟體開發商快速成長。
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中介軟體需要的Socket/Tcp框架實現了這麼一件有意思的事,把原生的Socekt基於資料流的流式通訊模式轉換為基於訊息的訊息通訊模式,讓開發人員多複雜的系統Socket通訊和資料流處理之中解放出來,轉而關心高層通訊訊息的設計和訊息處理的業務設計與實現。
三、AgileEAS.NET SOA 中介軟體Socket/Tcp框架重要的介面和類
AgileEAS.NET SOA中介軟體需要的Socket/Tcp框架嚴格意思是需要的基於Socket的通訊訊息中件間,其所提供的功能本質是對訊息的處理,所以其所提供的API有三大類、Socket框架本身、訊息框架及訊息處理框架,以下是AgileEAS.NET SOA中介軟體的Socket/Tcp的應用框架結構:
其中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框架是的一個基於訊息物件的訊息通訊框架,那麼其最核心的業務就是定義訊息及訊息的處理思路,我們稱之為訊息及訊息處理器結構:
其中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推向市場,讓更多的人使用。
我的技術團隊成員都是合作多年的老朋友,因為這個平臺是免費的,所以也沒有什麼收入,都是由程式設計師的那種理想與信念堅持,在此我感謝一起奮鬥的朋友。
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。