像qq这样的即时通信软件,时不时就会从桌面的右下角弹出一个小窗口,或是显示一个广告、或是一个新闻、或是一个公告等。在这里,我们将其统称为“全局系统通知”。很多使用c#开源即时通讯系统——ggtalk的朋友都建议我加上一个类似的功能,今天,ggtalk 5.1终于实现了这一功能,并且可以通过web后台发送全局系统通知。下面,我们将一步步讲述这一功能是如何实现的(通过类似同样的步骤,大家可以为ggtalk添加任意的自己需要的功能)。
1.定义消息类型和协议类
我们将全局系统通知分为两类:
(1)第一种通知,是发给所有用户的。
(2)第二种通知,是发给指定群组(group)中的用户的。
基于此,我们需要定义两种消息类型,于是,我们在ggtalk.core项目中的informationtypes 类下增加两个常量:
///
/// 发送给所有用户的系统消息
///
public const int systemnotify4allonline = ; ///
/// 发送给某个组的系统消息
///
public const int systemnotify4group = ;
为了简便,我们让两个类型的消息公用同一个协议类,在ggtalk.core项目中增加systemnotifycontract类:
///
/// 系统通知的协议类。
///
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(info, );
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(info, );
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接口中增加一个方法,用于发送系统通知:
///
/// 发送系统通知给所有在线用户。
///
void sendsystemnotify(string title, string content);
并且,在ggtalk.server项目的remotingservice类中,实现这个方法即可。
6.源码下载
ggtalk即时通信系统是可在部署运行的c#开源即时通信系统,2013.8.7发布v1.0版本,至今最新是5.1版本,关于gg更详细的介绍以及最新源码下载,请移步 可在广域网部署运行的c#开源即时通信系统 -- ggtalk总览。