如何通过WCF技术实现无人终端的远程监控功能?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1793个文字,预计阅读时间需要8分钟。
在项目中遇到了一个需要在远程监控自动运行软件的实时情况的需求。考虑到MS面向服务端有WCF,并查阅了一些资料后,觉得WCF比较适合这个应用。因此决定使用WCF来实现这个功能。
-最进在项目中,遇到了一个需要在远程监视自动运行软件的实时情况的例子。因为MS面向服务方面有WCF,而且看了一些资料,觉得WCF比较适合这个应用。因此决定用WCF来实现这个功能。
首先,先说一下具体的应用,监控,顾名思义,有两个方面的意思,一方面是”监”,也就是远程要能实时查看终端的各种情况。这里其实指的就是被监控的要能主动的,实时的向远程控制端发送自己的情况。另一方面是控,即远程端能够发布命令控制终端进行执行。并由终端返回一定的执行信息。
而且这里是一种一对一对多的关系,即一个终端可以被多个管理端监控。实际上一个管理端也可以监控多个终端,在是这种分析中,我们可以明白,真正运行服务的是终端,而不是管理端。
简单起见,假定远程发送命令的操作是void Operation(),终端更新的操作是UpdateStatus();
这个想法,从设计到实现,经历以下三种阶段的变形。
最初的想法,是一个Service类。一个接口。即
即控制端调用operation发送命令,终端调用UpdateStatus更新状态。
对应的,要有一定的回调,即控制端发送Operation时,终端要有一个callBack进行接收,相应的,当终端用UpdateStatus时,控制端也要有一个callBack进行接收。
当这两种操作被集成到一个服务中时,我们的wcf接口变成了如下结构。
namespaceGeyunfei.WCF
{
[ServiceContract(
SessionMode=SessionMode.Required
,
CallbackContract=typeof(ISeviceCallBack)
)]
publicinterfaceIService
{
[OperationContract]
///<summary>
///远程发送控制命令
///</summary>
///
voidOperation();
[OperationContract]
///<summary>
///更新状态
///</summary>
voidUpdateStatus();
}
publicinterfaceISeviceCallBack
{
voidReceiveStatus();
voidReceiveCommand();
}
publicstaticclassGlobal
{
publicstaticList<ISeviceCallBack>callBacks=newList<ISeviceCallBack>();
}
[ServiceBehavior]
publicclassService:IService,IDisposable
{
ISeviceCallBackcallBack;
#regionIServiceMembers
publicService()
{
callBack=System.ServiceModel.OperationContext.Current.GetCallbackChannel<ISeviceCallBack>();
Global.callBacks.Add(callBack);
}
///<summary>
///当服务端调用这个时,向终端发命令
///</summary>
publicvoidOperation()
{
foreach(varrinGlobal.callBacks)
{
r.ReceiveCommand();
}
}
///<summary>
///当终端调用时,向服务端发命令
///</summary>
publicvoidUpdateStatus()
{
foreach(varrinGlobal.callBacks)
{
r.ReceiveStatus();
}
}
#endregion
#regionIDisposableMembers
publicvoidDispose()
{
Global.callBacks.Remove(this.callBack);
}
#endregion
}
}
这样做实现起来比较方便,但是缺点也是很明显的,因为实际上终端只需要调用updateStatus,并回调receiveCommand,而管理端只需要调用Operation,回调receiveUpdateStatus(),现在这两种操作同时暴露给了终端和管理端 ,因此从设计上,这是一种不安全设计。。而且在调用相应的操作时,服务端自己又回得到相应的callBack,让人感到很费解。
那么下一步的想法,显然是把面向终端和管理端的服务进行分开。同时,用全局的变量或MSMQ进行交互,这里为了简单起见,只使用了List<>,没有使用委托。
这时,我们的设计变成了如下的形式:
CodenamespaceGeyunfei.WCF2
{
///<summary>
///面向终端的服务
///</summary>
[ServiceContract(
SessionMode=SessionMode.Required
,
CallbackContract=typeof(ITerminalSeviceCallBack)
)]
publicinterfaceITerminalService
{
[OperationContract]
///<summary>
///更新状态
///</summary>
voidUpdateStatus();
}
///<summary>
///面向管理端的服务
///</summary>
[ServiceContract(
SessionMode=SessionMode.Required
,
CallbackContract=typeof(IControlSeviceCallBack)
)]
publicinterfaceIControlService
{
[OperationContract]
///<summary>
///远程发送控制命令
///</summary>
///
voidOperation();
}
publicinterfaceITerminalSeviceCallBack
{
voidReceiveCommand();
}
publicinterfaceIControlSeviceCallBack
{
voidReceiveStatus();
}
publicstaticclassGlobal
{
publicstaticList<IControlSeviceCallBack>controlcallBacks=newList<IControlSeviceCallBack>();
publicstaticList<ITerminalSeviceCallBack>terminalcallBacks=newList<ITerminalSeviceCallBack>();
}
[ServiceBehavior]
publicclassTerminalService:ITerminalService,IDisposable
{
ITerminalSeviceCallBackcallBack;
#regionIServiceMembers
publicTerminalService()
{
callBack=System.ServiceModel.OperationContext.Current.GetCallbackChannel<ITerminalSeviceCallBack>();
Global.terminalcallBacks.Add(callBack);
}
///<summary>
///当终端调用时,向服务端发命令
///</summary>
publicvoidUpdateStatus()
{
foreach(varrinGlobal.controlcallBacks)
{
r.ReceiveStatus();
}
}
#endregion
#regionIDisposableMembers
publicvoidDispose()
{
Global.terminalcallBacks.Remove(this.callBack);
}
#endregion
}
[ServiceBehavior]
publicclassControlService:IControlService,IDisposable
{
IControlSeviceCallBackcallBack;
#regionIServiceMembers
publicControlService()
{
callBack=System.ServiceModel.OperationContext.Current.GetCallbackChannel<IControlSeviceCallBack>();
Global.controlcallBacks.Add(callBack);
}
///<summary>
///当服务端调用这个时,向终端发命令
///</summary>
publicvoidOperation()
{
foreach(varrinGlobal.terminalcallBacks)
{
r.ReceiveCommand();
}
}
#endregion
#regionIDisposableMembers
publicvoidDispose()
{
Global.controlcallBacks.Remove(this.callBack);
}
#endregion
}
}
现在,终端和管理端的服务分开了,接口也清晰了。
但是这样做又有另一个缺点,即我的每一个终端是只运行一个软件的,即我在运行terminalService时,只有一个点在接入。这时,我为这一个点开一个服务,是一种浪费 。
于是,就有了第三种方案。即服务是面向管理端的。终端只实例一个简单的承载体,如下:
这时,我们的方案就已经接近完美了。
CodenamespaceGeyunfei.WCF3
{
[ServiceContract(
SessionMode=SessionMode.Required
,
CallbackContract=typeof(ISeviceCallBack)
)]
publicinterfaceIService
{
[OperationContract]
///<summary>
///远程发送控制命令
///</summary>
voidOperation();
}
publicinterfaceISeviceCallBack
{
voidReceiveStatus();
}
publicstaticclassGlobal
{
publicstaticList<ISeviceCallBack>callBacks=newList<ISeviceCallBack>();
publicstaticReceiveCommandHandlerreceiveCommad;
}
[ServiceBehavior]
publicclassService:IService,IDisposable
{
ISeviceCallBackcallBack;
#regionIServiceMembers
publicService()
{
callBack=System.ServiceModel.OperationContext.Current.GetCallbackChannel<ISeviceCallBack>();
Global.callBacks.Add(callBack);
}
///<summary>
///当终端调用时,向服务端发命令
///</summary>
publicvoidOperation()
{
if(Global.receiveCommad!=null)
Global.receiveCommad();
}
#endregion
#regionIDisposableMembers
publicvoidDispose()
{
Global.callBacks.Remove(this.callBack);
}
#endregion
}
publicdelegatevoidReceiveCommandHandler();
publicclassServiceHost
{
publicServiceHost()
{
}
publicvoidStart()
{
//在这里启动运行一个Service服务
}
publicvoidStop()
{
//在这里停止服务
}
///<summary>
///当收到远程的命令时,触发此事件
///</summary>
publiceventReceiveCommandHandlerReceveCommand
{
add
{
Global.receiveCommad+=value;
}
remove
{
Global.receiveCommad-=value;
}
}
///<summary>
///更新状态
///</summary>
publicvoidUpdateStatus()
{
foreach(varrinGlobal.callBacks)
{
r.ReceiveStatus();
}
}
}
}
以上是我在开发中的一些体会,从第一种到第三种,可能老鸟们看着很弱智,只接就能使用第三种设计,但是对于一个初学者,直接想到这种方案可能比较困难,欢迎大家讨论。
本文共计1793个文字,预计阅读时间需要8分钟。
在项目中遇到了一个需要在远程监控自动运行软件的实时情况的需求。考虑到MS面向服务端有WCF,并查阅了一些资料后,觉得WCF比较适合这个应用。因此决定使用WCF来实现这个功能。
-最进在项目中,遇到了一个需要在远程监视自动运行软件的实时情况的例子。因为MS面向服务方面有WCF,而且看了一些资料,觉得WCF比较适合这个应用。因此决定用WCF来实现这个功能。
首先,先说一下具体的应用,监控,顾名思义,有两个方面的意思,一方面是”监”,也就是远程要能实时查看终端的各种情况。这里其实指的就是被监控的要能主动的,实时的向远程控制端发送自己的情况。另一方面是控,即远程端能够发布命令控制终端进行执行。并由终端返回一定的执行信息。
而且这里是一种一对一对多的关系,即一个终端可以被多个管理端监控。实际上一个管理端也可以监控多个终端,在是这种分析中,我们可以明白,真正运行服务的是终端,而不是管理端。
简单起见,假定远程发送命令的操作是void Operation(),终端更新的操作是UpdateStatus();
这个想法,从设计到实现,经历以下三种阶段的变形。
最初的想法,是一个Service类。一个接口。即
即控制端调用operation发送命令,终端调用UpdateStatus更新状态。
对应的,要有一定的回调,即控制端发送Operation时,终端要有一个callBack进行接收,相应的,当终端用UpdateStatus时,控制端也要有一个callBack进行接收。
当这两种操作被集成到一个服务中时,我们的wcf接口变成了如下结构。
namespaceGeyunfei.WCF
{
[ServiceContract(
SessionMode=SessionMode.Required
,
CallbackContract=typeof(ISeviceCallBack)
)]
publicinterfaceIService
{
[OperationContract]
///<summary>
///远程发送控制命令
///</summary>
///
voidOperation();
[OperationContract]
///<summary>
///更新状态
///</summary>
voidUpdateStatus();
}
publicinterfaceISeviceCallBack
{
voidReceiveStatus();
voidReceiveCommand();
}
publicstaticclassGlobal
{
publicstaticList<ISeviceCallBack>callBacks=newList<ISeviceCallBack>();
}
[ServiceBehavior]
publicclassService:IService,IDisposable
{
ISeviceCallBackcallBack;
#regionIServiceMembers
publicService()
{
callBack=System.ServiceModel.OperationContext.Current.GetCallbackChannel<ISeviceCallBack>();
Global.callBacks.Add(callBack);
}
///<summary>
///当服务端调用这个时,向终端发命令
///</summary>
publicvoidOperation()
{
foreach(varrinGlobal.callBacks)
{
r.ReceiveCommand();
}
}
///<summary>
///当终端调用时,向服务端发命令
///</summary>
publicvoidUpdateStatus()
{
foreach(varrinGlobal.callBacks)
{
r.ReceiveStatus();
}
}
#endregion
#regionIDisposableMembers
publicvoidDispose()
{
Global.callBacks.Remove(this.callBack);
}
#endregion
}
}
这样做实现起来比较方便,但是缺点也是很明显的,因为实际上终端只需要调用updateStatus,并回调receiveCommand,而管理端只需要调用Operation,回调receiveUpdateStatus(),现在这两种操作同时暴露给了终端和管理端 ,因此从设计上,这是一种不安全设计。。而且在调用相应的操作时,服务端自己又回得到相应的callBack,让人感到很费解。
那么下一步的想法,显然是把面向终端和管理端的服务进行分开。同时,用全局的变量或MSMQ进行交互,这里为了简单起见,只使用了List<>,没有使用委托。
这时,我们的设计变成了如下的形式:
CodenamespaceGeyunfei.WCF2
{
///<summary>
///面向终端的服务
///</summary>
[ServiceContract(
SessionMode=SessionMode.Required
,
CallbackContract=typeof(ITerminalSeviceCallBack)
)]
publicinterfaceITerminalService
{
[OperationContract]
///<summary>
///更新状态
///</summary>
voidUpdateStatus();
}
///<summary>
///面向管理端的服务
///</summary>
[ServiceContract(
SessionMode=SessionMode.Required
,
CallbackContract=typeof(IControlSeviceCallBack)
)]
publicinterfaceIControlService
{
[OperationContract]
///<summary>
///远程发送控制命令
///</summary>
///
voidOperation();
}
publicinterfaceITerminalSeviceCallBack
{
voidReceiveCommand();
}
publicinterfaceIControlSeviceCallBack
{
voidReceiveStatus();
}
publicstaticclassGlobal
{
publicstaticList<IControlSeviceCallBack>controlcallBacks=newList<IControlSeviceCallBack>();
publicstaticList<ITerminalSeviceCallBack>terminalcallBacks=newList<ITerminalSeviceCallBack>();
}
[ServiceBehavior]
publicclassTerminalService:ITerminalService,IDisposable
{
ITerminalSeviceCallBackcallBack;
#regionIServiceMembers
publicTerminalService()
{
callBack=System.ServiceModel.OperationContext.Current.GetCallbackChannel<ITerminalSeviceCallBack>();
Global.terminalcallBacks.Add(callBack);
}
///<summary>
///当终端调用时,向服务端发命令
///</summary>
publicvoidUpdateStatus()
{
foreach(varrinGlobal.controlcallBacks)
{
r.ReceiveStatus();
}
}
#endregion
#regionIDisposableMembers
publicvoidDispose()
{
Global.terminalcallBacks.Remove(this.callBack);
}
#endregion
}
[ServiceBehavior]
publicclassControlService:IControlService,IDisposable
{
IControlSeviceCallBackcallBack;
#regionIServiceMembers
publicControlService()
{
callBack=System.ServiceModel.OperationContext.Current.GetCallbackChannel<IControlSeviceCallBack>();
Global.controlcallBacks.Add(callBack);
}
///<summary>
///当服务端调用这个时,向终端发命令
///</summary>
publicvoidOperation()
{
foreach(varrinGlobal.terminalcallBacks)
{
r.ReceiveCommand();
}
}
#endregion
#regionIDisposableMembers
publicvoidDispose()
{
Global.controlcallBacks.Remove(this.callBack);
}
#endregion
}
}
现在,终端和管理端的服务分开了,接口也清晰了。
但是这样做又有另一个缺点,即我的每一个终端是只运行一个软件的,即我在运行terminalService时,只有一个点在接入。这时,我为这一个点开一个服务,是一种浪费 。
于是,就有了第三种方案。即服务是面向管理端的。终端只实例一个简单的承载体,如下:
这时,我们的方案就已经接近完美了。
CodenamespaceGeyunfei.WCF3
{
[ServiceContract(
SessionMode=SessionMode.Required
,
CallbackContract=typeof(ISeviceCallBack)
)]
publicinterfaceIService
{
[OperationContract]
///<summary>
///远程发送控制命令
///</summary>
voidOperation();
}
publicinterfaceISeviceCallBack
{
voidReceiveStatus();
}
publicstaticclassGlobal
{
publicstaticList<ISeviceCallBack>callBacks=newList<ISeviceCallBack>();
publicstaticReceiveCommandHandlerreceiveCommad;
}
[ServiceBehavior]
publicclassService:IService,IDisposable
{
ISeviceCallBackcallBack;
#regionIServiceMembers
publicService()
{
callBack=System.ServiceModel.OperationContext.Current.GetCallbackChannel<ISeviceCallBack>();
Global.callBacks.Add(callBack);
}
///<summary>
///当终端调用时,向服务端发命令
///</summary>
publicvoidOperation()
{
if(Global.receiveCommad!=null)
Global.receiveCommad();
}
#endregion
#regionIDisposableMembers
publicvoidDispose()
{
Global.callBacks.Remove(this.callBack);
}
#endregion
}
publicdelegatevoidReceiveCommandHandler();
publicclassServiceHost
{
publicServiceHost()
{
}
publicvoidStart()
{
//在这里启动运行一个Service服务
}
publicvoidStop()
{
//在这里停止服务
}
///<summary>
///当收到远程的命令时,触发此事件
///</summary>
publiceventReceiveCommandHandlerReceveCommand
{
add
{
Global.receiveCommad+=value;
}
remove
{
Global.receiveCommad-=value;
}
}
///<summary>
///更新状态
///</summary>
publicvoidUpdateStatus()
{
foreach(varrinGlobal.callBacks)
{
r.ReceiveStatus();
}
}
}
}
以上是我在开发中的一些体会,从第一种到第三种,可能老鸟们看着很弱智,只接就能使用第三种设计,但是对于一个初学者,直接想到这种方案可能比较困难,欢迎大家讨论。

