人生是一场不能存盘的RPG,我只能尽量多搞几个Screenshot

May 16, 2006

Webcast_使用.NET Remoting 建立分布式应用程序

Filed under: Web cast学习

//—————————————————-
    第1讲   
//—————————————————-   
Remoting 使用的技术
    XML
    SOAP
    SerializableAttribute()  或实现ISerializable
 
    //==Bin
    FileStream fs = new FileStream("my.bin" , FileMode.Creat);
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(fs , myObj);
    fs.Close();
   
    //==Soap
    FileStream fs = new FileStream("my.xml" , FileMode.Creat);
    SoapFormatter formatter = new SoapFormatter();
    formatter.Serialize(fs , myObj);
    fs.Close();
      
    //==XML
    FileStream fs = new FileStream("my.xml" , FileMode.Creat);
    System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(MyType));
    xmlSer.Serialize(fs , myObj);
    fs.Close();
   
远程对象:
    对象运行在远程(MarshalByRefObject)
    传递对象副本(Serialize)
   
对象激活
    服务器激活SAO(WellKnown)
        Singleton
        SingleCall
    客户端激活   
        可保存会话状态

Channels
    用于收发消息
    TCP or Http, 也可自定义
   
开发remoting的步骤
    创建远程对象
        public class HelloServer: MarshalByRefObject
        {
            public
        }
   
    创建host程序, 或host在IIS中
        注册通道(内置: TCP , HTTP)
        注册服务器激活的远程对象, URL
        运行宿主对象
   
    建立客户端程序
        注册通道(内置: TCP , HTTP)
        根据URL得到对象代理
        通过代理调用远程对象.
       
    //===Sample : SampleRemoting   
    public class Client
 {
        public static void Main(string[] args)
        {
            //使用TCP通道得到远程对象
            TcpChannel chan1 = new TcpChannel();
            ChannelServices.RegisterChannel(chan1);
            HelloServer obj1 = (HelloServer)Activator.GetObject(typeof(RemotingSamples.HelloServer),"tcp://localhost:8085/SayHello");
            if (obj1 == null)
            {
                System.Console.WriteLine("Could not locate TCP server");
            }
           
            //使用HTTP通道得到远程对象
            HttpChannel chan2 = new HttpChannel();
            ChannelServices.RegisterChannel(chan2);
            HelloServer obj2 = (HelloServer)Activator.GetObject(typeof(RemotingSamples.HelloServer), "http://localhost:8086/SayHello");
            if (obj2 == null)
            {
                System.Console.WriteLine(
                    "Could not locate HTTP server");
            }

            Console.WriteLine( "Client1 TCP HelloMethod {0}", obj1.HelloMethod("Caveman1"));
            Console.WriteLine("Client2 HTTP HelloMethod {0}", obj2.HelloMethod("Caveman2"));
            Console.ReadLine();
        }
/*
            <configuration>
             <system.runtime.remoting>
              <application>
               <client>
                <wellknown type="HelloServer, General" url="http://localhost:8086/SayHello" />
               </client>
               <channels>
                <channel ref="http" port="0"></channel>
               </channels>
              </application>
             </system.runtime.remoting>
            </configuration>
           
           
   RemotingConfiguration.Configure(@"C:\Documents and Settings\RenMin\桌面\Remoting\Demo\02-SimpleRemoting\Client\client.exe.config");
   HelloServer obj2 = new HelloServer();
*/
 }
 
 public class Server
 {
  public static int Main(string [] args)
  {

   TcpChannel chan1 = new TcpChannel(8085);
   HttpChannel chan2 = new HttpChannel(8086);

            //注册通道, server会开始监听该通道
   ChannelServices.RegisterChannel(chan1);
   ChannelServices.RegisterChannel(chan2);

            RemotingConfiguration.RegisterWellKnownServiceType( typeof(HelloServer),
                                                                "SayHello" ,                    //URL
                                                                WellKnownObjectMode.Singleton   //对象类型
                                                              );

   System.Console.WriteLine("Press Enter key to exit");
   System.Console.ReadLine();

   return 0;
  }
    }
   
    //==Remote object
    public class HelloServer : MarshalByRefObject
    {
        public HelloServer()
        {
            Console.WriteLine("HelloServer activated");
        }
        public String HelloMethod(String name)
        {
            Console.WriteLine( "Server Hello.HelloMethod : {0}", name);
            return "Hi there " + name;
        }
    }
   
}

可传递的类型:
    简单类型
    可序列化的类型
    自定义的类型[serializable]
   
    在Client端直接使用User class
   
Singleton VS SingleCall
    都是服务器激活(WellKnown)
    Singleton :
        在服务器端只实例化一次
        每次调用都是同一实例.
        可以维持状态
    SingleCall
        每次调用都实例化新的实例
       
Serialization vs MarshalByRefObject
    Serialization
        副本,不论Singleton还是SingleCall
    MarshalByRefObject
        通过proxy   
         Singleton记录更改, SingleCall无状态
        
   
    判断一个obj是否是一个Proxy
    RemotingServices.IsTransparentProxy()
   
//—————————————————-
    第2讲   
//—————————————————-  
 
SAO 配置文件 wellknown
<configuration>
    <system.runtime.remoting>
        <application>
            <service>
                <wellknown mode="Singleton" objectUri="SayHello" type="RemotingSamples.HelloServer, General" />
            </service>
            <channels>
                <channel port="8086" ref="http"/>
            </channels>
        </application>
    </system.runtime.remoting>
</configuration>

<service>说明是server端
ref实际上是引用machine.config
%WINDIR%\Microsoft.NET\Framework\[version]\CONFIG
<channels>
    <channel id="http" type=" "…/>
</channels>

客户端配置文件
<configuration>
    <system.runtime.remoting>
        <application>
            <client>
                <wellknown url="http://localhost:8086/SayHello" type="RemotingSamples.HelloServer, General" />
            </client >
            <channels>
                <channel port="0" ref="http"/>
            </channels>
        </application>
    </system.runtime.remoting>
</configuration>

<channel port="0" />client
不需要监听

–代码——————————————————-
Server.cs
    public class Server
 {
  public static int Main(string [] args)
  {
            RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
            //or RemotingConfiguration.Configure("Server.exe.config");

   System.Console.WriteLine("Press Enter key to exit");
   System.Console.ReadLine();
   return 0;
  }
 }
   
Client.cs
    public class Client
    {
        public static void Main(string[] args)
        {
            //使用HTTP通道得到远程对象
            RemotingConfiguration.Configure(@"client.exe.config");
            HelloServer obj2 = new HelloServer();
            if (obj2 == null)
            {
                System.Console.WriteLine("Could not locate HTTP server");
            }

            Console.WriteLine( "Client2 HTTP HelloMethod {0}", obj2.HelloMethod("Caveman2"));
            Console.ReadLine();
        }
    }

基于租约的对象生存期
可参考
使用.NET Remoting开发分布式应用——基于租约的生存期
http://terrylee.cnblogs.com/archive/2005/11/28/285809.html

    微软的DCOM技术使用了Ping机制,在这种机制下,客户程序有规律的对服务程序发出Ping请求,
以通知服务程序自己仍旧活着,并通知服务程序自己需要使用哪个对象。
    .NET Remoting使用的是基于租约的生存期机制,在租约期内,对象一直存活着,直到租借时间
结束,.NET Remoting使用Leasing程序完成了这项工作。

隐式续约
    每次调用远程对象上的方法的时候自动进行。
显示的续约
    ILease.Renew()
发起租约
    ISponsor接口
    ILease.Register()
   
   
租约的配置
    租约配置                默认值(秒)
    LeaseManagerPollTime       300
    SponsorshipTimeout         120
    RenewOnCallTime            120
    InitialLeaseTime (轮讯时间)          10        
   
//–如何得到当前的租约
HelloServer obj = (HelloServer)Activator.GetObject(typeof(RemotingSamples.HelloServer), "http://localhost:8086/SayHello");

ILease lease = (ILease)obj.GetLifetimeService();

if (lease != null)
{
    Console.WriteLine("Lease Configuration:");
    Console.WriteLine("InitialLeaseTime: " +
        lease.InitialLeaseTime);
    Console.WriteLine("RenewOnCallTime: " +
        lease.RenewOnCallTime);
    Console.WriteLine("SponsorshipTimeout: " +
        lease.SponsorshipTimeout);
    Console.WriteLine(lease.CurrentLeaseTime);
}  

//–通过代码改变租约, 见 Helloserver.cs
// Overrides the lease settings for this object.
public override Object InitializeLifetimeService()
{

    ILease lease = (ILease)base.InitializeLifetimeService();
    // Normally, the initial lease time would be much longer.
    // It is shortened here for demonstration purposes.
    if (lease.CurrentState == LeaseState.Initial)
    {
        lease.InitialLeaseTime = TimeSpan.FromSeconds(3);
        lease.SponsorshipTimeout = TimeSpan.FromSeconds(10);
        lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
    }
    return lease;
}

//–通过配置改变租约, 见 server的web.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <system.runtime.remoting>
  <application>
         ….
   <!–leaseManagerPollTime="7S"–>
   <lifetime leaseTime="7M"  sponsorshipTimeout="7M"  renewOnCallTime="7M"/>
  </application>
 </system.runtime.remoting>
</configuration>

CAO客户端激活 activated
   客户端激活的server端config文件
   <application>
   <service>
    <activated type="ClientActivatedType, General"/>
   </service>
   </application>
  
   client 端config文件
  
   <application>
   <client url="http://localhost:8080">
    <activated type="ClientActivatedType, General"/>
   </client>
   </application>

  
   优点客户端可以保存客户状态
        例子为 04-CAOsDemo
       
   客户端发起租约
        例子为 05-SponserDemo
       
   客户端发起租约的代码
        public class MyClientSponsor : MarshalByRefObject, ISponsor
        {
       
            private DateTime lastRenewal;
       
            public MyClientSponsor()
            {
                lastRenewal = DateTime.Now;
            }
       
            public TimeSpan Renewal(ILease lease)
            {
       
                Console.WriteLine("I’ve been asked to renew the lease.");
                Console.WriteLine("Time since last renewal:" + (DateTime.Now - lastRenewal).ToString());
       
                lastRenewal = DateTime.Now;
                return TimeSpan.FromSeconds(20);
            }
        }

        public class Client
        {
       
            public static void Main(string[] Args)
            {
                // Loads the configuration file.
                RemotingConfiguration.Configure("client.exe.config");
       
                ClientActivatedType CAObject = new ClientActivatedType();
       
                ILease serverLease = (ILease)RemotingServices.GetLifetimeService(CAObject);
                MyClientSponsor sponsor = new MyClientSponsor();
       
                // Note: If you do not pass an initial time, the first request will
                // be taken from the LeaseTime settings specified in the
                // server.exe.config file.
                serverLease.Register(sponsor);
                …… 
            }
        }

//—————————————————-
    第3讲   
//—————————————————-  
程序发布的模式: console, winform, winService, IIS

需要看源代码

//—————————————————-
    第4讲   
//—————————————————-  
聊天程序

  
  
  

Comments »

The URI to TrackBack this entry is: http://recordsome.blogsome.com/2006/05/16/p42/trackback/

No comments yet.

RSS feed for comments on this post.

Leave a comment

Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>



Anti-spam measure: please retype the above text into the box provided.






















Get free blog up and running in minutes with Blogsome
Theme designed by Hadley Wickham