.Net 3.5 Remoting编程入门二

.Net 3.5 Remoting编程入门二

什么是激活方式?

简单的理解:我们知道,在我们的Remoting应用需要远程处理对象,那么这些对象是怎么创建的?又是由谁去创建的呢?而激活方式则正是要说明这些疑问。

远程对象的激活方式分为:

服务器激活与客户端激活两种主要的方式,

其中服务器激活方式中又分为SingleCall(单调用)和Singleton(单例)。

当服务器激活模式为SingleCall时:

当每个客户端调用远程服务器上的对象时,服务端会为每个客户端产生一个对象供其使用,当客户端使用完毕后,此对象将被撤消。

当服务器激活模式为Singleton时:

当每个客户端调用远程服务器上的对象时,服务端仅客户端产生一个对象供其使用,当客户端使用完毕后,由对象并不被撤消,而是一直保持服务器端,以便其他客户端或下次调用。

客户端激活其用法和类似本地创建的对象。只是,客户端激活在一个单独的应用域中的宿主上运行,由起代理调用。

 

现在,我们在代码的基础上,学习各种激活方式。

首先,创建一个类Message.cs,这个类就是我们需要远程调用处理的类。这个类与第一章中的类是基本相同,我们现在只是增加了一个ID,方便我们后面的比较。

using System;

namespace RemotingClass

{

    public class Message : MarshalByRefObject

    {

        public Guid MessageId { get; set; } //Guid,用于保存MessageID

        public Message()

        {

            this.MessageId = Guid.NewGuid();//当对象被实例同时产生一个ID

        }

        public delegate void MessageHandler(string msg);

        public static event MessageHandler OnSendMessage;

        public void SendMessage(string msg)

        {

            if (OnSendMessage != null)

                OnSendMessage("MessageID:" + this.MessageId + msg);//为了看的清楚,把ID打印出来

        }

    }

}

 

服务端代码:使用Singleton激活

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting.Channels.Http;

 

namespace Server

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("Host Started!");

            HttpChannel channel = new HttpChannel(20001);

            ChannelServices.RegisterChannel(channel,false);

            RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingClass.Message), "Message", WellKnownObjectMode.Singleton); //这里使用Singleton即代表使用服务端的Singleton激活方式

            RemotingClass.Message.OnSendMessage += new RemotingClass.Message.MessageHandler(Message_OnSendMessage);

 

            Console.Read();

 

        }

        public static void Message_OnSendMessage(string msg)

        {

            Console.WriteLine(msg);

        }

    }

}

 

客户端代码:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting.Channels.Http;

namespace Client

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("Client Started!");

            HttpChannel channel = new HttpChannel();

            ChannelServices.RegisterChannel(channel, false);

            RemotingConfiguration.RegisterWellKnownClientType(typeof(RemotingClass.Message), "http://localhost:20001/Message");//因采用的是服务端激活方式,所以客户端只需要注册对象类型和uri即可

            RemotingClass.Message msg = new RemotingClass.Message();

            while (true)

            {

                msg.SendMessage(" 现在是:" + System.DateTime.Now.ToString());

                System.Threading.Thread.Sleep(2000);

            }

            //Console.ReadLine();

        }

 

    }

}

好了,代码编写完毕,然后编译运行,先运行服务端程序,再启动客户端程序,我们可以在服务端程序的界面看到,MessageID每次都是一样的,说明,尽管客户端是每过2秒调用一次远程的对象,但是,每次调用都是同一个对象。

 

再来看看,服务器激活SingleCall方式。

只需要修改服务端程序的代码,如下:

            RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingClass.Message), "Message", WellKnownObjectMode.SingleCall); //只需要将这里由原来的SingletonSingleCall即可

         

其他代码,远程类Message和客户端代码不需要修改。

然后编译运行,先运行服务端程序,再启动客户端程序,我们可以在服务端程序的界面看到,

MessageID是每次都不一样的。说明,尽管客户端是每过2秒调用一次远程的对象,但是,每次调用都是都是一个全新的对象。

 

 

最后,我们来看看客户端激活方式。

第一步,远程处理的Message类不需要修改。

第二步,修改服务端程序,如下:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting.Channels.Http;

 

namespace Server

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("Host Started!");

            HttpChannel channel = new HttpChannel(20001);

            ChannelServices.RegisterChannel(channel, false);

            //  RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingClass.Message), "Message", WellKnownObjectMode.SingleCall); //这里使用SingleCall即可

            RemotingConfiguration.RegisterActivatedServiceType(typeof(RemotingClass.Message));//注意这个地方与上面注释掉的代码是不同。采用客户端激活方式,服务端只需要对象类型即可。也就是告诉大家,来吧,这个类型可以远程调用

            RemotingClass.Message.OnSendMessage += new RemotingClass.Message.MessageHandler(Message_OnSendMessage);

 

            Console.Read();

        }

        public static void Message_OnSendMessage(string msg)

        {

            Console.WriteLine(msg);

        }

    }

}

 

第三步,修改客户端程序,如下:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting.Channels.Http;

namespace Client

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("Client Started!");

            HttpChannel channel = new HttpChannel();

            ChannelServices.RegisterChannel(channel, false);

            // RemotingConfiguration.RegisterWellKnownClientType(typeof(RemotingClass.Message), "http://localhost:20001/Message");

            RemotingConfiguration.RegisterActivatedClientType(typeof(RemotingClass.Message), "http://localhost:20001");//现在由客户端来激活对象,所以它需要对象类型以及在服务端的url

            RemotingClass.Message msg = new RemotingClass.Message();

            while (true)

            {

                msg.SendMessage(" 现在是:" + System.DateTime.Now.ToString());

                System.Threading.Thread.Sleep(2000);

            }

            //Console.ReadLine();

        }

 

    }

}

然后编译运行,先运行服务端程序,再启动客户端程序,我们可以在服务端程序的界面看到,

MessageID没有变。因为客户端激活对象创建以后,可以多次调用。

 

 

那么什么时候采用客户端激活?什么时候采用服务器激活呢?

在客户端激活模式中,每个客户端都创建自己的对象,并能多次调用该对象。由于并发客户创建大量对象可能耗尽系统资源,所以这种模式的可扩展性不太好。如果预期的用户比较少,而且需要维护调用期间的状态信息时,可以考虑使用这个模式。

服务器激活方式可实现单例和单调用。

单例最适合在多用户之间共享一个资源或者协同操作,如聊天室。

如果客户端需要执行服务器上相对较短的操作,而且不需要为下一次调用保存状态信息,此时应可以使用单调用。这种方式最具有扩展性,而且能在利用负载平衡将调用指向对个服务器的环境中很好的工作。

以上代码是在VS2008 SP中C#3.0写的。

OK,就写到这里,明天要上班,后面我们在一起继续学习!

 

posted @ 2008-11-10 01:11  ♂风车车  阅读(1109)  评论(2编辑  收藏  举报