天天看點

廣播與P2P通道(下) -- 方案實作

1.P2P通道狀态

根據上文模型3的讨論,要實作該模型,每個用戶端需要知道自己與哪些使用者建立了P2P通道,伺服器也要知道每個用戶端已建立的P2P通道的狀态。

(1)P2PChannelManager

我們在服務端設計P2PChannelManager類來管理每個線上用戶端已成功建立的所有P2P通道。

P2PChannelManager提供了注冊P2P通道、登出P2P通道、以及查詢P2P通道是否存在的方法。其内部使用類似字典的SortedArray來管理每個使用者的已經成功建立的P2P通道(即與哪些其它使用者打通了P2P)。另外,P2PChannelManager預定了IUserManager的SomeOneDisconnected事件,這樣,當某個使用者掉線時,就可以清除其所有的P2P狀态。因為,在ESFramework中,當用戶端與伺服器的TCP連接配接斷開時,用戶端會自動關閉所有的P2P通道。

(2)用戶端實時報告自己的P2P狀态變化給服務端

當用戶端每次成功建立一個P2P通道、或者已有P2P通道中斷時,用戶端要發消息告訴服務端。這樣,我們就需要定義這個消息的類型:

再定義消息協定:

定好了消息類型和contract類,我們在用戶端預定P2P通道的狀态變化,并報告給服務端:

在服務端,我們需要處理這兩種類型的消息(實作ICustomizeHandler接口的HandleInformation方法):

這樣,服務端就實時地知道每個用戶端的P2P狀态了。

2.與廣播結合

同樣的,我們首先為廣播消息定義一個消息類型:

再定義對應的協定類:

(1)在用戶端發送廣播消息

在用戶端,我們根據與組内成員的P2P通道的狀态,來判斷發送的方案,就像依據上文提到的,可細分為三種情況:

a.當某個用戶端發現自己群組内的所有其它成員都建立了P2P通道時,那麼,它就不用把廣播消息發送給伺服器了。

b.如果用戶端與組内的所有其它成員的P2P通道都沒有建立成功,那麼,它隻需要将廣播消息發送給伺服器。

c.如果用戶端與部分組内的成員建立了P2P通道,那麼,它不僅需要将廣播消息發送給伺服器,還需要将該廣播消息經過每個P2P通道發送一次。 

 (2)服務端轉發廣播

當伺服器收到一個廣播消息時,首先,檢視目标組中的使用者,然後,根據廣播消息的發送者的P2P通道狀态,來綜合決定該廣播消息需要轉發給哪些用戶端。我們隻需在上面的HandleInformation方法中增加代碼就可以了:

(3)用戶端處理接收到的廣播消息

用戶端也隻要實作ICustomizeHandler接口的HandleInformation方法,就可以處理來自P2P通道或者轉發自服務端的廣播消息了(即處理MyInfoTypes.Broadcast類型的消息),這裡就不贅述了。 

實際上,本文的實作還可以進一步優化,特别是在高頻的廣播消息時(如前文舉的視訊會議的例子),這種優化效果是很明顯的。那就是,比如,我們在用戶端可以将組内的成員分成兩類管理起來,一類是P2P已經打通的,一類是沒有通的,并根據實際的P2P狀态變化而調整。這樣,用戶端每次發送廣播消息時,就不用周遊自己與每個組員的P2P通道的狀态,這可以節省不少的cpu時間。同理,服務端也可以如此處理。

繼續閱讀