天天看點

.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,用于儲存Message的ID

        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("Message的ID是:" + 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();

        }

    }

}

好了,代碼編寫完畢,然後編譯運作,先運作服務端程式,再啟動用戶端程式,我們可以在服務端程式的界面看到,Message的ID每次都是一樣的,說明,盡管用戶端是每過2秒調用一次遠端的對象,但是,每次調用都是同一個對象。

.Net 3.5 Remoting程式設計入門二

再來看看,伺服器激活SingleCall方式。

隻需要修改服務端程式的代碼,如下:

            RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingClass.Message), "Message", WellKnownObjectMode.SingleCall); //隻需要将這裡由原來的Singleton換SingleCall即可

其他代碼,遠端類Message和用戶端代碼不需要修改。

然後編譯運作,先運作服務端程式,再啟動用戶端程式,我們可以在服務端程式的界面看到,

Message的ID是每次都不一樣的。說明,盡管用戶端是每過2秒調用一次遠端的對象,但是,每次調用都是都是一個全新的對象。

.Net 3.5 Remoting程式設計入門二

最後,我們來看看用戶端激活方式。

第一步,遠端處理的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();

        }

    }

}

然後編譯運作,先運作服務端程式,再啟動用戶端程式,我們可以在服務端程式的界面看到,

Message的ID沒有變。因為用戶端激活對象建立以後,可以多次調用。

.Net 3.5 Remoting程式設計入門二

那麼什麼時候采用用戶端激活?什麼時候采用伺服器激活呢?

在用戶端激活模式中,每個用戶端都建立自己的對象,并能多次調用該對象。由于并發客戶建立大量對象可能耗盡系統資源,是以這種模式的可擴充性不太好。如果預期的使用者比較少,而且需要維護調用期間的狀态資訊時,可以考慮使用這個模式。

伺服器激活方式可實作單例和單調用。

單例最适合在多使用者之間共享一個資源或者協同操作,如聊天室。

如果用戶端需要執行伺服器上相對較短的操作,而且不需要為下一次調用儲存狀态資訊,此時應可以使用單調用。這種方式最具有擴充性,而且能在利用負載平衡将調用指向對個伺服器的環境中很好的工作。

以上代碼是在VS2008 SP中C#3.0寫的。

OK,就寫到這裡,明天要上班,後面我們在一起繼續學習!