您所在的位置: 首页>>开发>>语言&工具>>

通过实例分析WCF Duplex消息交换(2)

http://developer.51cto.com  2008-03-14 14:36  张逸  博客园  我要评论(0)
  • 摘要:作为实现SOA体系架构的技术框架,WCF最重要的特征就在于能够定义和提供服务。以聊天室程序为例,虽然服务端会参与消息的交互,但却不应该参与到聊天中。也就是说,客户端与服务端的角色任务是不相同的。
  • 标签:WCF  Duplex  消息  交换

服务提供了Join、Say、Whisper与Leave等接口方法,向对应的是回调接口的接口方法。在实现IChat服务接口的服务类ChatService中,定义了委托ChatEventHandler与ChatEventHandler类型的事件ChatEvent,正是通过它实现了识别了客户的消息广播。方法如下:

private void BroadcastMessage(ChatEventArgs e)
{
ChatEventHandler temp = ChatEvent;

if (temp != null)
{
foreach (ChatEventHandler handler in temp.GetInvocationList())
{
handler.BeginInvoke(this, e, new AsyncCallback(EndAsync), null);
}
}
}


在客户端加入聊天室程序之前,该客户端并没有订阅ChatEvent事件,此时调用BroadcastMessage方法,在通过GetInvocationList方法获取MulticastDelegate时,不存在该客户端的委托实例。因而,其他客户在通过聊天室进行聊天时,不会将聊天信息发送到该客户端。体现在程序中,就是Join方法的如下代码片断:

myEventHandler = new ChatEventHandler(MyEventHandler);

……

callback = OperationContext.Current.GetCallbackChannel();
ChatEventArgs e = new ChatEventArgs();
e.msgType = MessageType.UserEnter;
e.name = name;
BroadcastMessage(e);
ChatEvent += myEventHandler;
……

注意看,ChatEvent += myEventHandler语句是放在BroadcastMessage方法调用之后。一旦该客户端加入聊天室程序之后,再调用BroadcastMessage方法,该客户端就能接收消息了。

ChatEvent事件指向的方法是MyEventHandler,该方法将执行回调接口的相关方法:

private void MyEventHandler(object sender, ChatEventArgs e)
{
try
{
switch (e.msgType)
{
case MessageType.Receive:
callback.Receive(e.name, e.message);
break;
case MessageType.ReceiveWhisper:
callback.ReceiveWhisper(e.name, e.message);
break;
case MessageType.UserEnter:
callback.UserEnter(e.name);
break;
case MessageType.UserLeave:
callback.UserLeave(e.name);
break;
}
}
catch
{
Leave();
}
}

   
还需要注意的是Whisper方法。由于它实现了私聊功能,因而向指定客户发送信息时,不应该采用广播方式。如何找到指定客户呢?这需要一个Dictionary集合,保存客户名和与之对应的ChatEventHandler实例。在执行Whisper方法时,就可以根据客户名找到对应的ChatEventHandler实例进行调用:

public void Whisper(string to, string msg)
{
ChatEventArgs e = new ChatEventArgs();
e.msgType = MessageType.ReceiveWhisper;
e.name = this.name;
e.message = msg;
try
{
ChatEventHandler chatterTo;
lock (syncObj)
{
chatterTo = chatters[to];
}
chatterTo.BeginInvoke(this, e, new AsyncCallback(EndAsync), null);
}
catch (KeyNotFoundException)
{
}
}


在客户端代码中,服务接口的调用采用了异步调用的方式,例如客户端加入聊天室:

proxy = new ChatProxy(site);
IAsyncResult iar = proxy.BeginJoin(myNick, new AsyncCallback(OnEndJoin), null);


运行聊天室程序时,服务端仅需要提供稳定而持续的服务。聊天的参与者均为客户端用户。因而服务端的运行代码如下所示:

Uri uri = new Uri(ConfigurationManager.AppSettings["addr"]);
ServiceHost host = new ServiceHost(typeof(NikeSoftChat.ChatService), uri);
host.Open();
Console.WriteLine("Chat service listen on endpoint {0}", uri.ToString());
Console.WriteLine("Press ENTER to stop chat service...");
Console.ReadLine();
host.Abort();
host.Close();


本文Sample的作者是Nikola Paljetak。鉴于作者本人在代码所附的许可声明,为了帮助大家阅读本文,在此附上Nikola Paljetak的Sample,你可以在WCF官方网站中找到它。Nikola Paljetak的许可声明如下:

Permission is granted to anyone to use this software for any purpose, including commercial applications.

【责任编辑:碧海蓝天 TEL:(010)68476606】



共2页: 上一页 [1] 2
【内容导航】
WCF开发基础
交换机故障解决指南
交换机的安全配置与安全漫谈
交换机的选购
交换技术配置手册
 
 验证码: (点击刷新验证码)   匿名发表
  • Visual C++ 完全自学宝典

  • 作者:强锋科技,朱洪波
  • Visual C++ 6.0是微软公司为程序人员提供的Visual Studio 6.0工具套件中的重要组成部分。本书由浅入深地介绍使用Visual C++ 6.0..
Copyright©2005-2008 51CTO.COM 版权所有