ESFramework介绍之(21)-- Tcp组件接口ITcp介绍
生活随笔
收集整理的這篇文章主要介紹了
ESFramework介绍之(21)-- Tcp组件接口ITcp介绍
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
??? ??? 寫了這么多篇介紹ESFramework的文章才想起來還有一些很基礎的內容沒有介紹,前面介紹的一些組件、框架基本上是與協議無關的(比如無論是Tcp還是Udp甚至是Remoting、WebService都可以通用),然而到了應用的最底層,我們總需要選擇一種通信協議,.net Framework對Remoting和WebService已經封裝的足夠好了,而對Tcp和Udp提供的API還是很低級,所以ESFramework對這兩種協議進行了高層的封裝,而且這些封裝與ESFramework的其它組件協調一致,合作起來天衣無縫!
??? 本文就先從封裝的Tcp組件開始介紹(Tcp組件的前身可以參見.NET平臺下可復用的Tcp通信層實現 和 .NET平臺下可復用的Tcp通信層實現(續) )。
??? 支持ESFramework的Tcp組件都需要實現ITcp接口:
???
?1???? public?interface?ITcp?:?ITcpClientsController?,IDisposable
?2?????{
?3?????????void?Initialize()?;????????
?4?????????void?Start()?;
?5?????????void?Stop()?;?//釋放所有連接
?6?
?7?????????int??Port{get?;set?;}????????
?8?????????int??ConnectionCount{get?;}?//當前連接的數量
?9?????????int??RecieveBuffSize{get?;set?;}
10?????????int??MaxMessageSize{set?;}?//當發現的消息長度大于MaxMessageSize,將關閉對應的連接
11?
12?????????ITcpStreamDispatcher?Dispatcher{set;}?//支持依賴注入
13?????????IContractHelper??????ContractHelper{set?;}
14?????????IBufferPool??????????BufferPool{set?;}?
15?????????IEsbLogger?????????????EsbLogger{set?;}??//記錄運行日志
16?
17?????????event?CbSimpleInt????SomeOneConnected?;????//上線?,ConnectID????????
18?????????event?CbSimpleInt????ConnectionCountChanged?;//在線人數變化
19?
20?????????event?CallBackDisconnect?SomeOneDisConnected?;?//掉線?,ConnectID
21?????????event?CallBackRespond????ServiceCommitted?;//用戶請求的服務的回復信息????
22?????????event?CallBackRespond????ServiceDirectCommitted?;//對應ITcpClientsController.SendData?,此時無法確定ServiceKey????????
23?????}????
24?
25?????public?delegate?void?CallBackRespond(int?connectID?,NetMessage?msg)?;
26?????public?delegate?void?CallBackDisconnect(int?connectID?,DisconnectedCause?cause)?;????
??? 上面接口定義中的注釋已經解釋了大多數內容,額外地,我需要解釋一下幾件事情:
(1)為什么ITcp沒有從一個更基礎的接口比如INet繼承,這樣ITcp和IEsbUdp(后面將要介紹的Udp組件的基礎接口)就有了共同的根源?
??? 早在EnterpriseServerBase中確實是這樣設計的,但是在ESFramework中卻將它們嚴格的隔離開來,原因在于,Tcp與Udp是如此的不同,如果要它們相互遷就共同遵守同一個“有意義”的基礎接口并不是一件愉快的事情。這里說的“有意義”,指的是,我們可以通過這個接口來幾乎完整的操縱不同的Tcp組件和Udp組件,而不需要進行向下轉換。我們曾在一個早期的應用中,使之即支持Tcp協議,有支持Udp協議,只需簡單修改一下配置文件,就可以簡單的從一個協議切換到另一個。我們實現了這個目標,但是程序的實現中摻雜了太多的if...else和向下轉換,有人一定會建議,使用多態可以避免if...else,讓我告訴你這樣做的難處在哪里。如果使用多態替換if...else,就需要將更多的東西抽象到形式一致的接口中,但是,Tcp和Udp組件的很多方法的簽名是無法達成一致的,除非都使用Object類型,可是,如果都使用Object類型的參數,在方法的實現中,仍然需要向下進行轉換。可見這樣做并沒有任何好處。首先是使得邏輯更加復雜含混,而且對效率也沒有任何幫助。
??? 所以太不相同的事物,就沒有必要給它們安排一個共同的祖先。也許,我們可以給予一個沒有多大意義的基礎接口,比如像
????public?interface?INet
????{
????????void?Initialize()?;????????
????????void?Start()?;
????????void?Stop()?;?
????????int??Port{get?;set?;}????????
????} ??? 這沒有多大的用處。如果有一天,ESFramework發現了可以從ITcp和IEsbUdp中抽象出一個有意義的基礎接口的時候,會重構來得到這個接口,這也是很簡單的。
(2)通過MaxMessageSize屬性可以設置應用中所允許的單個消息的最大長度,如果從某連接上接收到的消息的長度大于此值,則Tcp組件會關閉對應的連接。如果對消息長度沒有限制,則可以設置為int.MaxValue。
(3)Dispatcher屬性是為Tcp組件設置消息分配器,每當Tcp組件接收到一個完整的消息,就會把它交給分配器進行分派處理。消息分配器是ESFramework的核心組件,前面已經做了詳細介紹。
(4)BufferPool是緩沖區池,如果tcp發現即將接收的消息的長度大于RecieveBuffSize屬性給定的值,則會從BufferPool申請更大的緩沖區來接收消息,為了避免大緩沖區的重復創建/銷毀的開銷,并增加復用,所以使用BufferPool來管理較大的緩沖區。
???
??? public?interface?IBufferPool
????{
????????byte[]?RentBuffer(int?minSize)?;
????????void??? GivebackBuffer(byte[]?buffer)?;
????}
(5)ServiceCommitted事件,當服務器處理完一個用戶請求并把回復發送出去后,將觸發該事件。如果ServiceCommitted事件被引發,表示回復數據已經被發送出去了。
(6)我們看到了ITcp從ITcpClientsController繼承,ITcpClientsController接口用于服務器主動控制TCP客戶的連接,比如,在消息分配器組件中可能需要控制ITcp組件來直接向某個用戶發送Active數據,這時只需要引用ITcpClientsController就可以了。
??? public?interface?ITcpClientsController
????{????????
????????//主動給某個客戶同步發信息
????????void?SendData(int?ConnectID?,NetMessage?msg)?;????
????????//主動關閉連接
????????void?DisposeOneConnection(int?connectID?,DisconnectedCause?cause)?;
????}????
??? 關于ITcp的介紹就是這些,然而如何實現ITcp卻有多種方法,不同的實現方法所得到的并發量和效率可能千差萬別。所以ITcp的實現對與系統的效率和并發量有著非常關鍵的影響。ESFramework中ITcp的參考實現是AgileTcp(將在后文中講述),如果你有更好的實現,完全可以在采用ESFramework框架的同時使用自己實現的Tcp組件,ESFramework為你保留了這種權利--ESFramework所有的重要組件都是可以替換的,只要遵循相同的接口即可:)
????感謝關注!
?轉到??:ESFramework 可復用的通信框架(序)
??? 本文就先從封裝的Tcp組件開始介紹(Tcp組件的前身可以參見.NET平臺下可復用的Tcp通信層實現 和 .NET平臺下可復用的Tcp通信層實現(續) )。
??? 支持ESFramework的Tcp組件都需要實現ITcp接口:
???
?1???? public?interface?ITcp?:?ITcpClientsController?,IDisposable
?2?????{
?3?????????void?Initialize()?;????????
?4?????????void?Start()?;
?5?????????void?Stop()?;?//釋放所有連接
?6?
?7?????????int??Port{get?;set?;}????????
?8?????????int??ConnectionCount{get?;}?//當前連接的數量
?9?????????int??RecieveBuffSize{get?;set?;}
10?????????int??MaxMessageSize{set?;}?//當發現的消息長度大于MaxMessageSize,將關閉對應的連接
11?
12?????????ITcpStreamDispatcher?Dispatcher{set;}?//支持依賴注入
13?????????IContractHelper??????ContractHelper{set?;}
14?????????IBufferPool??????????BufferPool{set?;}?
15?????????IEsbLogger?????????????EsbLogger{set?;}??//記錄運行日志
16?
17?????????event?CbSimpleInt????SomeOneConnected?;????//上線?,ConnectID????????
18?????????event?CbSimpleInt????ConnectionCountChanged?;//在線人數變化
19?
20?????????event?CallBackDisconnect?SomeOneDisConnected?;?//掉線?,ConnectID
21?????????event?CallBackRespond????ServiceCommitted?;//用戶請求的服務的回復信息????
22?????????event?CallBackRespond????ServiceDirectCommitted?;//對應ITcpClientsController.SendData?,此時無法確定ServiceKey????????
23?????}????
24?
25?????public?delegate?void?CallBackRespond(int?connectID?,NetMessage?msg)?;
26?????public?delegate?void?CallBackDisconnect(int?connectID?,DisconnectedCause?cause)?;????
??? 上面接口定義中的注釋已經解釋了大多數內容,額外地,我需要解釋一下幾件事情:
(1)為什么ITcp沒有從一個更基礎的接口比如INet繼承,這樣ITcp和IEsbUdp(后面將要介紹的Udp組件的基礎接口)就有了共同的根源?
??? 早在EnterpriseServerBase中確實是這樣設計的,但是在ESFramework中卻將它們嚴格的隔離開來,原因在于,Tcp與Udp是如此的不同,如果要它們相互遷就共同遵守同一個“有意義”的基礎接口并不是一件愉快的事情。這里說的“有意義”,指的是,我們可以通過這個接口來幾乎完整的操縱不同的Tcp組件和Udp組件,而不需要進行向下轉換。我們曾在一個早期的應用中,使之即支持Tcp協議,有支持Udp協議,只需簡單修改一下配置文件,就可以簡單的從一個協議切換到另一個。我們實現了這個目標,但是程序的實現中摻雜了太多的if...else和向下轉換,有人一定會建議,使用多態可以避免if...else,讓我告訴你這樣做的難處在哪里。如果使用多態替換if...else,就需要將更多的東西抽象到形式一致的接口中,但是,Tcp和Udp組件的很多方法的簽名是無法達成一致的,除非都使用Object類型,可是,如果都使用Object類型的參數,在方法的實現中,仍然需要向下進行轉換。可見這樣做并沒有任何好處。首先是使得邏輯更加復雜含混,而且對效率也沒有任何幫助。
??? 所以太不相同的事物,就沒有必要給它們安排一個共同的祖先。也許,我們可以給予一個沒有多大意義的基礎接口,比如像
????public?interface?INet
????{
????????void?Initialize()?;????????
????????void?Start()?;
????????void?Stop()?;?
????????int??Port{get?;set?;}????????
????} ??? 這沒有多大的用處。如果有一天,ESFramework發現了可以從ITcp和IEsbUdp中抽象出一個有意義的基礎接口的時候,會重構來得到這個接口,這也是很簡單的。
(2)通過MaxMessageSize屬性可以設置應用中所允許的單個消息的最大長度,如果從某連接上接收到的消息的長度大于此值,則Tcp組件會關閉對應的連接。如果對消息長度沒有限制,則可以設置為int.MaxValue。
(3)Dispatcher屬性是為Tcp組件設置消息分配器,每當Tcp組件接收到一個完整的消息,就會把它交給分配器進行分派處理。消息分配器是ESFramework的核心組件,前面已經做了詳細介紹。
(4)BufferPool是緩沖區池,如果tcp發現即將接收的消息的長度大于RecieveBuffSize屬性給定的值,則會從BufferPool申請更大的緩沖區來接收消息,為了避免大緩沖區的重復創建/銷毀的開銷,并增加復用,所以使用BufferPool來管理較大的緩沖區。
???
??? public?interface?IBufferPool
????{
????????byte[]?RentBuffer(int?minSize)?;
????????void??? GivebackBuffer(byte[]?buffer)?;
????}
(5)ServiceCommitted事件,當服務器處理完一個用戶請求并把回復發送出去后,將觸發該事件。如果ServiceCommitted事件被引發,表示回復數據已經被發送出去了。
(6)我們看到了ITcp從ITcpClientsController繼承,ITcpClientsController接口用于服務器主動控制TCP客戶的連接,比如,在消息分配器組件中可能需要控制ITcp組件來直接向某個用戶發送Active數據,這時只需要引用ITcpClientsController就可以了。
??? public?interface?ITcpClientsController
????{????????
????????//主動給某個客戶同步發信息
????????void?SendData(int?ConnectID?,NetMessage?msg)?;????
????????//主動關閉連接
????????void?DisposeOneConnection(int?connectID?,DisconnectedCause?cause)?;
????}????
??? 關于ITcp的介紹就是這些,然而如何實現ITcp卻有多種方法,不同的實現方法所得到的并發量和效率可能千差萬別。所以ITcp的實現對與系統的效率和并發量有著非常關鍵的影響。ESFramework中ITcp的參考實現是AgileTcp(將在后文中講述),如果你有更好的實現,完全可以在采用ESFramework框架的同時使用自己實現的Tcp組件,ESFramework為你保留了這種權利--ESFramework所有的重要組件都是可以替換的,只要遵循相同的接口即可:)
????感謝關注!
?轉到??:ESFramework 可復用的通信框架(序)
總結
以上是生活随笔為你收集整理的ESFramework介绍之(21)-- Tcp组件接口ITcp介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ESFramework介绍之(16)――
- 下一篇: 使用自定义参数