欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.NET Remoting学习笔记(二)激活方式

程序员文章站 2022-07-25 15:01:07
激活方式概念 在访问远程类型的一个对象实例之前,必须通过一个名为Activation的进程创建它并进行初始化。这种客户端通过通道来创建远程对象,称为对象的激活。  ...
激活方式概念

在访问远程类型的一个对象实例之前,必须通过一个名为Activation的进程创建它并进行初始化。这种客户端通过通道来创建远程对象,称为对象的激活。

 

 

 

 

 

服务器端激活

又称WellKnow(知名对象)

 

服务器应用程序在激活对象实例之前会在一个众所周知的统一资源标识符(URI)上来发布这个类型。然后该服务器进程会为此类型配置一个WellKnown对象,并根据指定的端口或地址来发布对象。

 

服务器端激活分为:SingleTon模式  SingleCall模式

 

 

 

SingleTon模式

设置为SingleTon激活方式,则Remoting将为所有客户端建立同一个对象实例。当对象处于活动状态时, SingleTon实例会处理所有后来的客户端访问请求,而不管它们是同一个客户端,还是其他客户端。SingleTon实例将在方法调用中一直维持其状态。举例来说,如果一个远程对象有一个累加方法(i=0;++i),被多个客户端(例如两个)调用。如果设置为SingleTon方式,则第一个客户获得值为1,第二个客户获得值为2,因为他们获得的对象实例是相同的。如果熟悉Asp .Net的状态管理,我们可以认为它是一种Application状态。

 

下面贴代码:

 

1.创建远程调用处理的类

 

 

复制代码

using System;

using System.Runtime.Remoting.Metadata;

 

/*code 释迦苦僧*/

namespace MessageMarshal

{

    /*创建发送消息委托*/

    public delegate void SendMessageHandler(string messge);

    [Serializable]

    public class TestMessageMarshal : MarshalByRefObject

    { 

        private Guid ID { get; set; }

        /*新建对象实例时重新创建标识编号*/

        public TestMessageMarshal()

        {

            ID = Guid.NewGuid();

        }

 

        /*创建发送消息事件*/

        public static event SendMessageHandler SendMessageEvent;

 

        /*发送消息*/

        [SoapMethod(XmlNamespace = "MessageMarshal", SoapAction = "MessageMarshal#SendMessage")]

        public void SendMessage(string messge)

        {

            if (SendMessageEvent != null)

                SendMessageEvent(ID.ToString() + "\t" + messge);

        }

    }

}

复制代码

2.创建服务端代码

 

 

复制代码

using System;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting.Channels.Http;

using MessageMarshal;

 

namespace TestRemotingServer

{

    /*code:释迦苦僧*/ 

    class Program

    {

        static void Main(string[] args)

        {

            /*创建HTTP通道*/

            HttpChannel channel = new HttpChannel(8226);

        

            /*注册通道服务端*/

            ChannelServices.RegisterChannel(channel,false);

            /*设置模式为 Singleton */

            RemotingConfiguration.RegisterWellKnownServiceType(typeof(TestMessageMarshal),"test", WellKnownObjectMode.Singleton);   

            Console.WriteLine("started ..."); 

            /*接收客户端事件*/ 

            TestMessageMarshal.SendMessageEvent+=new SendMessageHandler(TestMessageMarshal_SendMessageEvent);

            Console.Read();

        }

         

        static void TestMessageMarshal_SendMessageEvent(string messge)

        {

            Console.WriteLine(messge);

        }

    }

}

复制代码

3.创建客户端代码

 

 

复制代码

using System;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting.Channels.Http;

using System.Threading;

 

 

/*code 释迦苦僧*/

namespace TestRemotingClient

{

    class Program

    {

        static void Main(string[] args)

        {

            HttpChannel channel = new HttpChannel();

            ChannelServices.RegisterChannel(channel, false);

            /*注册通道 的 远程处理类型*/

            RemotingConfiguration.RegisterWellKnownClientType(typeof(MessageMarshal.TestMessageMarshal), "https://localhost:8226/test");

            /*创建消息实体*/

            MessageMarshal.TestMessageMarshal TestMessage = new MessageMarshal.TestMessageMarshal();

            while (true)

            {

                TestMessage.SendMessage("DateTime.Now:" + System.DateTime.Now.ToString());

                Console.WriteLine("send message...");

                Thread.Sleep(2000);

            }

        }

    }

}

复制代码

4.运行服务端后,开启两个客户端程序,查看结果如下:

 

 

 

代码示意中,当TestMessageMarshal有新实例时,其构造函数会创建不同的标识(GUID),服务端接收到客户端的数据请求,并将标识编号输出到界面,从界面中可以看出,多个客户端请求的通道,服务端都是用一个通道(一个实例)来进行处理的。

 

 

 

SingleCall模式

SingleCall是一种无状态模式。一旦设置为SingleCall模式,则当客户端调用远程对象的方法时, Remoting会为每一个客户端建立一个远程对象实例,至于对象实例的销毁则是由GC自动管理的。同上一个例子而言,则访问远程对象的两个客户获得的都是1。我们仍然可以借鉴Asp .Net的状态管理,认为它是一种Session状态。

 

我们修改服务端代码如下,客户端不需要修改:

 

            /*设置模式为 SingleCall */

            RemotingConfiguration.RegisterWellKnownServiceType(typeof(TestMessageMarshal),"test", WellKnownObjectMode.SingleCall);   

开启服务端,然后开启一个客户端,如下

 

 

从输出结果中可以看出,每次服务端都会为每一个客户端请求建立一个远程对象实例。

 

 

 

客户端激活

与WellKnown模式不同, Remoting在激活每个对象实例的时候,会给每个客户端激活的类型指派一个URI。客户端激活模式一旦获得客户端的请求,将为每一个客户端都建立一个实例引用。SingleCall模式和客户端激活模式是有区别的:首先,对象实例创建的时间不一样。客户端激活方式是客户一旦发出调用的请求,就实例化;而SingleCall则是要等到调用对象方法时再创建。其次,SingleCall模式激活的对象是无状态的,对象生命期的管理是由GC管理的,而客户端激活的对象则有状态,其生命周期可自定义。其三,两种激活模式在服务器端和客户端实现的方法不一样。尤其是在客户端,SingleCall模式是由 GetObject()来激活,它调用对象默认的构造函数。而客户端激活模式,则通过CreateInstance()来激活,它可以传递参数,所以可以调用自定义的构造函数来创建实例。

 

1.修改服务端代码

 

 

复制代码

using System;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting.Channels.Http;

using System.Runtime.Remoting.Channels.Tcp;

using MessageMarshal;

 

namespace TestRemotingServer

{

    /*code:释迦苦僧*/ 

    class Program

    {

        static void Main(string[] args)

        {

            /*创建HTTP通道*/

            HttpChannel channel = new HttpChannel(8226);

        

            /*注册通道服务端*/

            ChannelServices.RegisterChannel(channel,false);

            RemotingConfiguration.ApplicationName = "test";

            RemotingConfiguration.RegisterActivatedServiceType(typeof(TestMessageMarshal));   

            Console.WriteLine("started ..."); 

            /*接收客户端事件*/ 

            TestMessageMarshal.SendMessageEvent+=new SendMessageHandler(TestMessageMarshal_SendMessageEvent);

            Console.Read();

        }

         

        static void TestMessageMarshal_SendMessageEvent(string messge)

        {

            Console.WriteLine(messge);

        }

    }

}

复制代码

2.修改客户端代码

 

 

复制代码

using System;

using System.Runtime.Remoting;

using System.Runtime.Remoting.Channels;

using System.Runtime.Remoting.Channels.Http;

using System.Threading;

 

 

/*code 释迦苦僧*/

namespace TestRemotingClient

{

    class Program

    {

        static void Main(string[] args)

        {

            HttpChannel channel = new HttpChannel();

            ChannelServices.RegisterChannel(channel, false);

            /*注册通道 的 远程处理类型*/

            RemotingConfiguration.RegisterActivatedClientType(typeof(MessageMarshal.TestMessageMarshal), "https://localhost:8226/test");

            /*创建消息实体*/

            MessageMarshal.TestMessageMarshal TestMessage = new MessageMarshal.TestMessageMarshal();

            while (true)

            {

                TestMessage.SendMessage("DateTime.Now:" + System.DateTime.Now.ToString());

                Console.WriteLine("send message...");

                Thread.Sleep(2000);

            }

        }

    }