WCF 项目应用连载[3] - 双向通信 实例管理与服务端监控
WCF 项目应用连载[1] - 索引 - 轻量级的Log系统 - Lig Sample -序
第二节我们已经创建了Lig项目,并且能稳定工作了。现在我们来改进ILigAgent接口,实现WCF的双向通信。
3.1 双向通信
_________________________________________________________________________________
ILigAgent 增加订阅-发布 接口
3.1.1 关于订阅 – 发布
1) 发布-订阅设计模式又称观察者模式,它是软件设计模式中的一种,有一点要明白,它并不是WCF中所特有,正好相反,WCF中的双向通信只是这种模式中的一种应用。
2) WCF采用回调接口来进行双向通信,每一个服务接口允许存在有且只能存在一个回调接口。可以用ServiceContract中的CallbackContract属性进行显式声明指定定该服务接口的回调接口。
3) 回调接口由客户端实现。Server端通过一个静态的OperationContext对象获取客户端回调实例,我们用该实例在Server端调用回调接口,即可将消息发送给Client端。
OperationContext.Current.GetCallbackChannel<T>
如你所愿
1) 我们为ILigAgent增加了RegisterClient操作接口与Subcribe接口,Subcribe用于订阅服务端的消息。
2) 同时增加了ILigAgentCallback回调接口,用来在Server端实现消息推送。回调接口我们增加OnNotifyOnline,用来客户端注册成功后,Server将生成的带ClientID信息的消息发送给注册的客户端。
注意:服务端不同的服务实例用不同的HashCode加以区分,这样允许同名客户端的存在。
[ServiceContract(CallbackContract = typeof(ILigAgentCallback))]
public interface ILigAgent
{
[OperationContract]
LigStatus RegisterClient(string name);
[OperationContract]
LigStatus UnregisterClient(int clientID);
[OperationContract]
LigStatus Subscribe(int clientID);
[OperationContract]
LigStatus Unsubscribe(int clientID); }
public interface ILigAgentCallback
{
[OperationContract(IsOneWay = true)]
void OnNotifyMessage(string message);
[OperationContract(IsOneWay = true)]
void OnNotifyOnline(LigArgs args);
}
3.1.2 增加 数据契约类 LigArgs
说了半天。我们还没有正式应用数据契约。现在我们增加数据契约类用来在客户端与服务端进行通信时的数据传输。
此处LigArgs可以写成LigArgs : EventArgs,这样LigArgs可以变成EventHandler的事件参数岂不更好吗?
致于为什么不这样写,我们后面写ILigger时会回答这个问题。因为那时Lig已经完善。
[DataContract]
public class LigArgs
{
public LigArgs() { }
[DataMember]
public int ClientID { get; set; }
[DataMember]
public int HashID { get; set; }
[DataMember]
public bool ConnectStatus { get; set; }
[DataMember]
public string ClientName { get; set; }
[DataMember]
public string Message { get; set; }
}
3.2 服务实例管理 – 增加客户端实例上下文类
_________________________________________________________________________________
1) 我们在LigAgent类的内部增加一个内部类ClientContext,即客户端实例上下文类,这儿用来描述所注册客户端的信息。
2) 同时增加一个静态表dicClientsContext,用来保存注册客户端信息,其键名采用独立的HashCode。
Client信息就可以保存在Server端,Server端通过CallbackInstance给订阅客户端发送订阅消息。当客户端异常离线,Server将离线客户端信息从dicClientsContext中移除,移除的Client信息会由GC自动实现垃圾回收(当然此处最佳方案是采用弱引用(WeakReference)对ClientContext进行管理在性能上会更高效)。这样实现了Server对客户端资源的有效管理。
private static Dictionary<int, ClientContext> dicClientsContext = new Dictionary<int, ClientContext>();
#region InnerClasses
class ClientContext
{
internal ClientContext() { }
internal bool IsRegistered { get; set; }
internal bool IsSubscribed { get; set; }
internal int ClientID { get; set; }
internal int HashID { get; set; }
internal string ClientName { get; set; }
internal ILigAgentCallback CallbackInstance { get; set; }
internal OperationContext Context { get; set; }
}
#endregion
3.3 客户端 – 增加LigAgentCallback类
_________________________________________________________________________________
1) 在ConnectServer中将ChannelFactory换成DuplexChannelFactory。
2) 并注册LigAgentCallback内部的事件。我们通过LigAgentCallback内部的事件将回调消息发送给客户端。
this.callbackInstance = new LigAgentCallback();
this.SubscribedEvents();
//this.chnl = new ChannelFactory<ILigAgent>(SERVICENAME);
this.chnl = new DuplexChannelFactory<ILigAgent>(callbackInstance,SERVICENAME); private delegate void MessageHandler(string message);
private delegate void OnlineHandler(LigArgs args); #region InnerClasses
class LigAgentCallback : ILigAgentCallback
{
internal LigAgentCallback() { }
internal event MessageHandler msgReceived;
internal event OnlineHandler onlined;
public void OnNotifyMessage(string message)
{
if (this.msgReceived != null)
{
this.msgReceived(message);
}
}
public void OnNotifyOnline(LigArgs args)
{
if (this.onlined != null)
{
this.onlined(args);
}
}
internal void Release()
{ }
}
#endregion
图 3.3.1 在 LigManager内部订阅 LigAgentCallback内部事件
3.4 关于服务端监控 - LigAgent
_________________________________________________________________________________
原理:LigManager封装了ILigAgent接口资源。在LigAgent内部通过注册OperationContext.Channel属性的Closed事件实现对客户端的异常与正常离线监控。
context.Context.Channel.Closed += new EventHandler(OnShowOffline)
LigAgent内部用于注册LigClient客户端的内部函数AddClient
private LigStatus AddClient(string name,out int clientID)
{
clientID = -1;
int hash = this.GetHashCode();
if (string.IsNullOrEmpty(name)) return LigStatus.InvalidClient; if (dicClientsContext.ContainsKey(hash)) return LigStatus.ClientExisted; clientID = LigCore.ActiveID; ClientContext context = new ClientContext();
context.ClientID = clientID;
context.ClientName = name;
context.HashID = hash;
context.IsRegistered = true;
context.Context = OperationContext.Current;
context.CallbackInstance = OperationContext.Current.GetCallbackChannel<ILigAgentCallback>(); context.Context.Channel.Closed += new EventHandler(OnShowOffline); dicClientsContext.Add(hash, context);
Console.WriteLine(LigCore.LiggedTime + "Client with hashCode [" + hash.ToString() + "] is online!");
return LigStatus.Success;
}
3.5 双向通信 服务端监控 测试
_________________________________________________________________________________
测试。
启动LigServer,同时启动5个LigClient客户端。写完日志记客户端离线。观看消息变化。
1) Server已经成功的实现了对Client信息的监控。当客户端异常或正常离线,服务端对客户端实例资源进行移动操作
2) LigClient注册成功后,收到了来自LigServer的信息。。。
图 3.3.2 LigServer-LigClient双向通信 服务端监控
图 3.3.3 LigServer-LigClient双向通信 服务端监控
图 3.3.3 LigServer-LigClient双向通信 服务端监控 LigClient收来来自LigServer的信息
好了。到这里为止。Lig系统已经差不多满足我们的要求了。但还是不太完善,Lig系统还有上升的空间。我们前面说过,要优化LigClient使用的.等你看完
WCF 项目应用连载[4] - 自定义配置 扩展ServiceHost
WCF 项目应用连载[5] - 自定义配置 扩展ChannelFactory<T> 后,
WCF 项目应用连载[6] - 升级Lig服务 - 设计ILigger
将回答这一问题。
WCF 项目应用连载[6] - 升级Lig服务 - 设计ILigger以后。Lig工程将是一个比较完美的版本。
本节的源代码下载:
_________________________________________________________________________________
Litelog -WCF 项目应用连载[3] - 双向通信 并发 实例管理与服务端监控 源代码.rar
_________________________________________________________________________________
WCF 项目应用连载[4] - 自定义配置 扩展ServiceHost
参考引文:
[1] Artech.WCF全面解析[M].2012
[2] O'Reilly.WCF编程[M].2009
[3] Adnrew Trolesen.C#与.net3.5/4高级程序设计[M].2009/2013
WCF 项目应用连载[3] - 双向通信 实例管理与服务端监控的更多相关文章
- WCF 项目应用连载[2] - 创建Lig日志系统
WCF 项目应用连载[1] - 索引 - 轻量级的Log系统 - Lig Sample -序 现在我们创建一个Lig工程 - Litelog 2.1 创建Lig服务 _________________ ...
- WCF 项目应用连载[8] - 绑定、服务、行为 大数据传输与限流 - 下 (ServiceThrottlingAttribute)
因为ORM的原因,对Attribute编程有一种情节..所以这节的出现,完全是因为在WCF对自定义Attribute的一种应用. WCF 项目应用连载[7] - 绑定.服务.行为 大数据传输与限流 - ...
- 实例PK(Vue服务端渲染 VS Vue浏览器端渲染)
Vue 2.0 开始支持服务端渲染的功能,所以本文章也是基于vue 2.0以上版本.网上对于服务端渲染的资料还是比较少,最经典的莫过于Vue作者尤雨溪大神的 vue-hacker-news.本人在公司 ...
- “快的打车”创始人陈伟星的新项目招人啦,高薪急招Java服务端/Android/Ios 客户端研发工程师/ mysql DBA/ app市场推广专家,欢迎大家加入我们的团队! - V2EX
"快的打车"创始人陈伟星的新项目招人啦,高薪急招Java服务端/Android/Ios 客户端研发工程师/ mysql DBA/ app市场推广专家,欢迎大家加入我们的团队! - ...
- loadrunner 编写socket脚本实例(附服务端实现)
一.socket背景知识 这个咱就不废话了,网上一搜一大堆 二.本实例实现的功能 服务端接收客户端发送的字符串,并返回"5678succ"共8个字符 三.服务端实现(java代码) ...
- socket基础实例(一个服务端对应一个客户端情形)
服务端处理1个客户端的例子 运行结果: (1) while(accept+if(recv)) 情形 执行服务端进程: [root@localhost single_link]# ./server [s ...
- pm2 工具来管理 node 服务端
如下: nodeServer.js 'use strict'; const http = require('http'); const server = http.createServer(funct ...
- Netty实例-简单的服务端-client实现,凝视具体
书籍推荐: 实例代码 :http://download.csdn.net/detail/jiangtao_st ...
- 一: WCF的服务端与客户端在通信时有三种模式:请求响应模式、数据报模式和双工通讯模式。
说一下基本知识, 1.如果想要将当前接口作为wcf服务器,则一定要加上[ServiceContract] 契约 2.要想将方法作为wcf服务方法发布给外部调用,则一定要加上 [Operatio ...
随机推荐
- 『重构--改善既有代码的设计』读书笔记----Move Method
明确函数所在类的位置是很重要的.这样可以避免你的类与别的类有太多耦合.也会让你的类的内聚性变得更加牢固,让你的整个系统变得更加整洁.简单来说,如果在你的程序中,某个类的函数在使用的过程中,更多的是在和 ...
- 使用程序往Neo4j导入CSV报错
今天在用程序向Neo4j导入csv文件时,报以下错误: java.net.ConnectException: Connection refused: connect java.rmi.ConnectE ...
- php之购物车类思路及代码
<?php /* 购物车类 1.整站范围内,购物车--全局有效 解决:把购物车的信息,放在session里 2.既然全局有效,购物车的实例只有一个 解决:单例模式 技术选型:session+单例 ...
- linux根目录下各文件的作用
各文件详列: /bin 存放常用命令的目录(二进制可执行命令) /dev 设备特殊文件 /etc 存放配置相关的文件(系统管理和配置文件) /etc/rc.d 启动的配置文件和脚 ...
- C#中静态方法和非静态方法的区别(一)
实例方法比静态方法多传递一个隐含的指针参数,该指针指向该方法所从属的已被实例化的对象.这一区别的外在表现为实例方法内可使用this关键字代表所从属的实例对象,而静态方法不可使用this因为静态方法不针 ...
- windows下实现uboot的tftp下载功能
一.原理分析 带有uboot的开发板实际上充当的就是tftp客户端,而PC机扮演的角色就是tftp服务器端,而tftp下载功能实际上就是文件传输.tftp服务器可以建立在虚拟机linux下,也可以建立 ...
- Reducing the Dimensionality of data with neural networks / A fast learing algorithm for deep belief net
Deeplearning原文作者Hinton代码注解 Matlab示例代码为两部分,分别对应不同的论文: . Reducing the Dimensionality of data with neur ...
- Following Orders
uva124:http://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=60题 ...
- 再来,LVS+KEEPALIVED
记得常规组合哟. 一般同时实现HA+LB. 如果只需要实现一个,那还不如UCARP?双机绑定一个IP作热备. CENTOS6:PACEMAKER+COROSYNC+HAPROXY. OTHER:HEA ...
- 使用 getNextException() 来检索已经过批处理的特定元素的异常。 ERRORCODE=-4228, SQLSTATE=null
今天查询了一天发现的问题,用ibatis做批量操作时,报错: [非原子批处理出现故障]使用 getNextException() 来检索已经过批处理的特定元素的异常. ERRORCODE=-4228, ...