[原创]DotNetRemoting演练,WebService与WindowsService的完美结合
WebService应用日益广泛,我们总希望能让WebService与后台应用结合起来,完成更加广泛的应用。.NET Remoting为分布式程序开发提供了高效开发方式。下面就由来抛砖引玉,让WebService与WindowsService结合起来完成一些简单的功能。
整个功能由4 部分组成:1个WebService+1个WindowsService+1个远程数据代理类+1个使用Remoting的API
1、远程数据代理类:
为什么从这里作为开端?由于Remoting核心说白了就是使用TCP或HTTP通道,来传输经过XML格式化的对象数据(个人看发哈,认为不对的就当我没说。)。那么传输的这个格式化对象能否被C/S两端进行序列化与反序列化就是至关重要的。
下面是远程数据类的代码
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
namespace RemotingClass
{
public delegate IRequestResult RequestUserData(object sender, RemotingDataClass msg);
[Serializable()]
public class RemotingDataClass
{
//远程类需要加此标记以表示此类可以序列化,不能序列化的类不能够通过Remoting进行传输。
//这个类是Client端到Server端进行传输参数所使用的。
//为了方便讲解,这里仅使用了2个数据字段iData和strData,实际情况可以根据需求进行修改。
public int iData;
public string StrData;
public RemotingDataClass()
{ }
}
public interface IRequestResult//服务器处理结果接口
{
string ErrorInfo
{
get;
set;
}
int Result
{
get;
set;
}
}
[Serializable()]
public class CRequestResult:IRequestResult
{
//服务器将数据处理后的结果信息
#region IRequestResult 成员
private string errorinfo;
private int result;
public string ErrorInfo
//ErrorInfo和Result都可以当作A,B这样的标识来看待,这是我用来测试时写的,没有具体意义.只是作为两个返回值传递回来.
{
get
{
return this.errorinfo;
}
set
{
this.errorinfo = value;
}
}
public int Result
{
get
{
return this.result;
}
set
{
this.result = value;
}
}
#endregion
}
public interface IRemotingClassBase
{
IRequestResult ProcessUserData(RemotingDataClass paramter);
}
public class CProcesser:System.MarshalByRefObject,IRemotingClassBase
{
//这个类是远程处理类,很重要.
//先定义一个事件,用于WebService向WindowsService传输数据后能够通知到WindowsService
public static event RequestUserData OnRecvRequestUserData;
//由于Remoting是有生存期的,加上这句话,生存期就是无限长的了
public override object InitializeLifetimeService()
{
return null;
}
#region IRemotingClassBase 成员
//远程处理类,调用之前得判断一下服务器端是否已经实现了该类
public IRequestResult ProcessUserData(RemotingDataClass paramter)
{
if (CProcesser.OnRecvRequestUserData != null)
{
return CProcesser.OnRecvRequestUserData(this,paramter);
}
else
{
CRequestResult result = new CRequestResult();
result.Result = 1100;
result.ErrorInfo = "服务器端未实现此客户端事件!";
return result;
}
}
#endregion
}
}
将这个工程编译。得到RemotingCass.DLL。这个DLL由下面的3个功能引用。
2、使用Remoting的API
OOP的一个重要思想--重用!写个API,任何调用此API的程序都可以使用.
废话少说,下面是API代码
将RemotingCass.DLL添加引用进来
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Channels;
namespace RemotingAPI
{
public class RemotingApiClass
{
//这里使用的是TCP通道,TCP通道要比HTTP通道速度快
System.Runtime.Remoting.Channels.Tcp.TcpClientChannel ClientChannel;
RemotingClass.CProcesser RemoteClass;
public RemotingApiClass(string ServerIP,int ServerPort)
{
//下面加红色的部分需要注意,这个名称是自定义的,但服务器端与客户端必须约定好,否则客户端无法找到对应的服务器端远程对象。
try
{
this.ClientChannel = new System.Runtime.Remoting.Channels.Tcp.TcpClientChannel();
ChannelServices.RegisterChannel(this.ClientChannel,true);
this.RemoteClass = (RemotingClass.CProcesser)Activator.GetObject(typeof(RemotingClass.CProcesser), "tcp://" + ServerIP + ":" + ServerPort + "/CProcesser");
}
catch
{ }
}
public RemotingClass.IRequestResult ProcessData(string strData, int iData)
{
if (this.RemoteClass == null)
{
RemotingClass.CRequestResult result = new RemotingClass.CRequestResult();
result.Result = 1101;
result.ErrorInfo = "连接服务器失败!";
return result;
}
RemotingClass.RemotingDataClass pam = new RemotingClass.RemotingDataClass();
pam.iData = iData;
pam.StrData = strData;
return this.RemoteClass.ProcessUserData(pam);
}
public void CloseChannel()
{
//这里是在不使用通道后,关闭通道。
try
{
ChannelServices.UnregisterChannel(this.ClientChannel);
}
catch
{ }
}
}
}
编译这个功能,得到API.DLL
3、WindowsService
这里没有编写太多的代码。建立一个WindowsService,增加了一段简单的处理。复杂的处理就留给各位兄弟自己开发吧。
将RemotingCass.DLL添加引用进来
private System.Runtime.Remoting.Channels.Tcp.TcpServerChannel ServerChannel;
protected override void OnStart(string[] args)
{
//在服务启动代码里需要注册通道,实例化远程类,注册事件,为接受远程处理请求做准备。
//红色标注的地方要与上边对应。
this.ServerChannel = new System.Runtime.Remoting.Channels.Tcp.TcpServerChannel(9900);
ChannelServices.RegisterChannel(this.ServerChannel,true);
System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingClass.CProcesser), "CProcesser", System.Runtime.Remoting.WellKnownObjectMode.SingleCall);
RemotingClass.CProcesser.OnRecvRequestUserData += new RemotingClass.RequestUserData(CProcesser_OnRecvRequestUserData);
}
//当有远程处理请求时,通过事件调用此段函数,真正的处理就在这里。
RemotingClass.IRequestResult CProcesser_OnRecvRequestUserData(object sender, RemotingClass.RemotingDataClass msg)
{
RemotingClass.CRequestResult result = new RemotingClass.CRequestResult();
result.ErrorInfo = "OK" + msg.StrData + "\\" + msg.iData.ToString();
//这。。。就这么处理。。。无语了。。。。。。
//哈哈,你要是看明白了,我就成功了。你要是愿意写,可以再写到日志文件里。
result.Result = 0;
return result;
}
4、WebService
同样,WebService也是一个简单的测试用例。建立一个WebService,加一个Web的函数。将远程数据类和API这两个DLL引用进来。就可以使用其中的远程处理函数了。
将RemotingCass.DLL和API.DLL添加引用进来
[WebMethod]
public string Processer(string strData, int iData)
{
RemotingAPI.RemotingApiClass agent = new RemotingAPI.RemotingApiClass("127.0.0.1", 9900);
RemotingClass.IRequestResult result = agent.ProcessData(strData, iData);
agent.CloseChannel();
return result.ErrorInfo;
}
这样就完成了整个功能,由于写的着急,以上代码没有经过实例测试,但这个方法我已经使用过很多了.今天没时间了,改天把代码测试一下发上来给大家使用.但用例是死的,人是活的,重要的不是代码,而是思想.希望上边的这段思想能够让大家对DotNetRemoting有所了解.
最后,感谢大家耐着性子看完了我这段,没头没尾,注释又少的代码和讲解.如有问题,欢迎跟贴,我将尽力为大家解决.
谢谢大家.