像QQ這樣的即時通信軟件,時不時就會從桌面的右下角彈出一個小窗口,或是顯示一個廣告、或是一個新聞、或是一個公告等。在這里,我們將其統稱為“全局系統通知”。很多使用C#開源即時通訊系統——GGTalk的朋友都建議我加上一個類似的功能,今天,GGTalk 5.1終於實現了這一功能,並且可以通過Web后台發送全局系統通知。下面,我們將一步步講述這一功能是如何實現的(通過類似同樣的步驟,大家可以為GGTalk添加任意的自己需要的功能)。
1.定義消息類型和協議類
我們將全局系統通知分為兩類:
(1)第一種通知,是發給所有用戶的。
(2)第二種通知,是發給指定群組(Group)中的用戶的。
基於此,我們需要定義兩種消息類型,於是,我們在GGTalk.Core項目中的InformationTypes 類下增加兩個常量:
/// <summary> /// 發送給所有用戶的系統消息 /// </summary> public const int SystemNotify4AllOnline = 80; /// <summary> /// 發送給某個組的系統消息 /// </summary> public const int SystemNotify4Group = 81;
為了簡便,我們讓兩個類型的消息公用同一個協議類,在GGTalk.Core項目中增加SystemNotifyContract類:
/// <summary> /// 系統通知的協議類。 /// </summary> public class SystemNotifyContract {
public SystemNotifyContract(string title, string content, string senderID ,string groupID) { this.Title = title; this.Content = content; this.SenderID = senderID; this.GroupID = groupID; } public string Title { get; set; } public string Content { get; set; } public string SenderID { get; set; } public string GroupID { get; set; } }
2.客戶端發送系統通知
(1)我們需要定義用於輸入系統通知的標題和內容的窗體,具體可參見GGTalk即時通訊系統項目源碼下的SystemNotifySendForm,當點擊窗體上的“發送”按鈕時:
private void btnSend_Click(object sender, EventArgs e) { try { SystemNotifyContract contract = new SystemNotifyContract(this.skinTextBox_id.Text, this.richTextBox1.Text, this.rapidPassiveEngine.CurrentUserID, this.skinTextBox_groupID.Text); byte[] data = CompactPropertySerializer.Default.Serialize(contract); int infoType = this.skinRadioButton_group.Checked ? InformationTypes.SystemNotify4Group : InformationTypes.SystemNotify4AllOnline; this.rapidPassiveEngine.CustomizeOutter.Send(infoType, data); MessageBox.Show("發送成功!"); this.Close(); } catch (Exception ee) { MessageBox.Show("發送失敗!" + ee.Message); } }
首先,需要構造協議類實例,然后使用緊湊的序列化器將其序列化,然后通過用戶的選擇確定是全局系統通知、還是組通知,最后使用通信引擎將消息其發送給服務端。
(2)SystemNotifySendForm實現完成后,我們需要在GGTalk客戶端住窗體的底部的功能菜單上添加一個“發送系統通知”的按鈕,當點擊該按鈕時,就new一個SystemNotifySendForm,並顯示出來給用戶輸入。
(3)如果需要,可以為該功能加上適當的權限控制,比如,只有管理員帳號登錄GGTalk后,才會看到“發送系統通知”的按鈕。
3.服務端處理
當服務端收到來自客戶端的全局系統通知消息時,需要將其廣播出去:
(1)如果是全局系統通知(SystemNotify4AllOnline ),則將其發送給所有在線的用戶。
(2)如果是群組系統通知(SystemNotify4Group),則將其發送給該組的所有成員。
下面是處理SystemNotify4Group類型消息的代碼(在GGTalk.Server項目的CustomizeHandler類中):
if (informationType == InformationTypes.SystemNotify4Group) { SystemNotifyContract contract = CompactPropertySerializer.Default.Deserialize<SystemNotifyContract>(info, 0); GGGroup group = this.globalCache.GetGroup(contract.GroupID); if (group != null) { foreach (string userID in group.MemberList) { this.rapidServerEngine.CustomizeController.Send(userID, InformationTypes.SystemNotify4Group, info); } } }
首先,需要反序列化得到SystemNotifyContract實例,然后拿到該實例中的GroupID的值,然后根據GroupID從緩存獲取該組的所有成員列表,最后,將系統通知轉發給所有這些成員。
4.客戶端顯示系統通知
當任何一個在線的GGTalk客戶端收到系統通知消息時,就會像QQ一樣在屏幕的右下角彈出一個小窗口,來顯示系統通知的具體內容。
(1)我們在GGTalk項目中增加一個SystemNotifyForm,用於顯示系統通知的信息。
(2)在客戶端的信息處理器中(在 MainFormPartial.cs 文件中),增加對SystemNotify4AllOnline 和 SystemNotify4Group消息的處理:
if (informationType == InformationTypes.SystemNotify4Group) { SystemNotifyContract contract = CompactPropertySerializer.Default.Deserialize<SystemNotifyContract>(info, 0); SystemNotifyForm form = new SystemNotifyForm(contract.Title, contract.Content); form.Show(); return; }
首先,將byte[]信息反序列化得到SystemNotifyContract,然后將其Title和Content交給SystemNotifyForm去顯示出來。
5.與Web后台集成
很多時候,我們的管理員可能都是通過Web后台來進行系統管理,並發送系統通知的,這樣,我們的GGTalk就需要與Web后台集成到一起。通常,GGTalk與Web的集成是這樣做的:
(1)GGTalk的服務端GGTalk.Server發布一個Remoting服務。
(2)Web通過調用GGTalk.Server的Remoting接口來完成與GGTalk的交互。
我們在GGTalk.Core項目中的IRemotingService接口中增加一個方法,用於發送系統通知:
/// <summary> /// 發送系統通知給所有在線用戶。 /// </summary> void SendSystemNotify(string title, string content);
並且,在GGTalk.Server項目的RemotingService類中,實現這個方法即可。
6.源碼下載
GGTalk即時通信系統是可在廣域網部署運行的C#開源即時通信系統,2013.8.7發布V1.0版本,至今最新是5.1版本,關於GG更詳細的介紹以及最新源碼下載,請移步 可在廣域網部署運行的C#開源即時通信系統 -- GGTalk總覽。