.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秒調用一次遠端的對象,但是,每次調用都是同一個對象。

再來看看,伺服器激活SingleCall方式。
隻需要修改服務端程式的代碼,如下:
RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingClass.Message), "Message", WellKnownObjectMode.SingleCall); //隻需要将這裡由原來的Singleton換SingleCall即可
其他代碼,遠端類Message和用戶端代碼不需要修改。
然後編譯運作,先運作服務端程式,再啟動用戶端程式,我們可以在服務端程式的界面看到,
Message的ID是每次都不一樣的。說明,盡管用戶端是每過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();
}
}
}
然後編譯運作,先運作服務端程式,再啟動用戶端程式,我們可以在服務端程式的界面看到,
Message的ID沒有變。因為用戶端激活對象建立以後,可以多次調用。
那麼什麼時候采用用戶端激活?什麼時候采用伺服器激活呢?
在用戶端激活模式中,每個用戶端都建立自己的對象,并能多次調用該對象。由于并發客戶建立大量對象可能耗盡系統資源,是以這種模式的可擴充性不太好。如果預期的使用者比較少,而且需要維護調用期間的狀态資訊時,可以考慮使用這個模式。
伺服器激活方式可實作單例和單調用。
單例最适合在多使用者之間共享一個資源或者協同操作,如聊天室。
如果用戶端需要執行伺服器上相對較短的操作,而且不需要為下一次調用儲存狀态資訊,此時應可以使用單調用。這種方式最具有擴充性,而且能在利用負載平衡将調用指向對個伺服器的環境中很好的工作。
以上代碼是在VS2008 SP中C#3.0寫的。
OK,就寫到這裡,明天要上班,後面我們在一起繼續學習!