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 ...
随机推荐
- Java----多线程知识点归纳(概念)
一.线程与进程的区别: 多个进程的内部数据和状态都是完全独立的,而多线程是共享一块内存空间和一组系统资源,有可能互相影响. ?线程本身的数据通常只有寄存器数据,以及一个 程序执行时使用的堆栈,所以线程 ...
- 【BZOJ3295】【块状链表+树状数组】动态逆序对
Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...
- OC 字符和日期的互转
需要用到NSDateFormatter这个类. 1.字符串转换为日期 [plain]NSDateFormatter* dateFormat = [[NSDateFormatter alloc] ini ...
- Ubuntu14 或是其他系统当中关于sublimeSFTP超时解决方法
一直都使用Sublime的SFTP功能,感觉还不错,好用,但是最近不知道怎么了,使用不成了,提示超时了,于是在网上找一下解决方法,没有找到,于是自己想着试试看,于在搞了一会,发现只要把配制文件当中的s ...
- iOS: 获取文件路径
iOS: 获取文件路径 // 例如 - (NSString *)applicationDocumentsDirectory { return [NSSearchPathForDirectories ...
- 利用Xilinx中的ROM构造查找表来计算sin和cos的方法探讨
1.使用matlab制作.coe文件 查找表的构造 构造256点的正余弦表 exp(-j*2*pi*(0:255)/256),分别得到 cos和sin的查找表 matlab代码: 求sin fid = ...
- 【转】nodejs
Node.JS + MongoDB技术讲座 云计算 + 大数据 = 未来. 在中国的云计算上基本上是一个概念,个人感觉与当初的SOA没有太大的区别,空泛的理论. 中小型开发的未来 ...
- oracle timestamp的转换
select to_char(stime,'yyyy-mm-dd HH24:MI:ss.ff3') from e_bmp_log_operation t where t.sdetail like '% ...
- 今天写了个从一张表数据插入到另一张表的oracle 语句
create or replace procedure data_move(param in number) is cursor enterprise is select SENTERPRISEID, ...
- 2014年Facebook的开源成就
2014是Facebook开源硕果丰硕的一年,其开源项目经理詹姆斯·皮尔斯(James Pearce)连续12天发布开源博客文章展示全年该社交网站在此领域取得的成就. 皮尔斯公布的成就包括以下内容: ...