标题:[原创]DotNetRemoting演练,WebService与WindowsService的完美结合
只看楼主
月夜枫华
Rank: 4
等 级:贵宾
威 望:12
帖 子:437
专家分:42
注 册:2006-1-2
 问题点数:0 回复次数:2 
[原创]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有所了解.

最后,感谢大家耐着性子看完了我这段,没头没尾,注释又少的代码和讲解.如有问题,欢迎跟贴,我将尽力为大家解决.
谢谢大家.
搜索更多相关主题的帖子: WebService 演练 结合 
2007-12-23 15:29
quanercao
Rank: 1
等 级:新手上路
帖 子:54
专家分:0
注 册:2007-10-16
得分:0 
3q 。。收藏了。。
2007-12-25 16:53
net开发
Rank: 2
等 级:论坛游民
帖 子:3
专家分:14
注 册:2013-6-19
得分:0 
hi,我是猎头echo,我这边有net开发   测试经理    研发主管   工程部经理等职位待遇优厚       136  6161  5785   QQ:2997790785
2013-06-19 09:24



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-194008-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.149854 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved