pursuedream
成功=水平+业务+沟通+判断
 Remoting是由DCOM演化而来,可以说的DCOM的升级,是解决分布式应用程序的重要技术。
 Remoting有三个部分组成,远程对象(一般为类库)、服务器和客户端。服务器和客户端都必须
 引用远程对   象DLL,已经固定System.Runtime.Remoting的DLL。服务器和客户端必须都开启.


远程对象:  指被客户端调用的类(类中包括在客户端实现的方法)。
                       该类有特殊要求,它必须属于以下三种中的一种:

            1.        按值排列的类,串行化通过通道,没有远程标识,不是透明代理,是真实代理,而
                       且必须实现 ISerializable或属性[Serializable] 。


                       透明代理:执行远程对象的所有公共方法,在执行时代用RealProxy和Invoke()方法。
                       在客户端通过以下代码进行验证:用类RemotingServices,命名空间System.Runtime.Remoting;
                     
                         if(RemotingServices.IsTransparentProxy(serialize))
                  
{
                                Console.WriteLine(
" 不是透明代理,是真实代理"
                            }

                      该类代码如下:
                    
                         [Serializable]
                         
public class mySerialized
                
{
                               
public void Food()
                    
{
                                       Console.WriteLine(
"mySerialized.Food is called");
                               }

                            }

            2.      按引用排列的类,有远程标识,有代理对象,是透明代理必须继承System.MarshalByRefObject类 
                     
                           public class Hello:System.MarshalByRefObject 
                 
{
                                   
public void Food()
                    
{
                                       Console.WriteLine(
"myRemote.Food is called");
                               }
 
                           }

           3.       不能用于远程通信的类,不常用

服务器:   启着实现远程对象代理的作用。首先它必须定义一个通道,为Http还是Tcp协议的通道,
                    接着把通道注册到Remoting中, 最后服务器注册远程对象类型,并指定客使用的URL和模式。

          1.       创建通道有类TcpServerChannel和HttpServerChannel,可以开通多通道,在实例该类时,
                    必须指定其端口号。或者也可以自己对该通道的详细说明,这样得要指定通道的传输
                    方式,是二进制符(较快)还是以SOAP符。

                    如下:
                    使用直接实例化
                    TcpServerChannel channel=new TcpServerChannel(8086); 或是Http
                    HttpServerChannel channel=new HttpServerChannel(8087);
      
                    或者添加相应属性:命名空间System.Collections.Specialized下ListDictionary                   

                          ListDictionary property=new ListDictionary();
                          
//通道使用的是SOAP标识符,也可以使用二进制
                          property.Add("Name","TCP channel with soap a formatter");
                          property.Add(
"Prority",5); //优先级为5
                          property.Add("port",8086); //端口为8086
                         
//把要传递的数据用SOAP格式符进行,也可以用二进制,类为BinaryServerFormatterSinkProvider
                  
        SoapServerFormatterSinkProvider soapProvid=new SoapServerFormatterSinkProvider();
                      
//把这种属性应用到通道中,其Http也是一样的
                          TcpServerChannel tChannel=new TcpServerChannel(property,soapProvider);

                    如果要查看通道的属性的话:(为上面的TcpServerChannel或HttpServerChannel对象)

                      protected static void showChannelProperty(IChannelReceiver channel)
            
{
                                Console.WriteLine(
"Name :"+channel.ChannelName);
                                Console.WriteLine(
"Priority :"+channel.ChannelPriority);//优先级
                                 
//如果是HTTP协议
                                if(channel is HttpChannel)
                         
{
                                        HttpChannel hChannel
=channel as HttpChannel;
                                        
//监听类型
                                        Console.WriteLine("Scheme :"+hChannel.ChannelScheme);
                                   }

                                    
//存储远程通道数据,获取通道数据
                                        ChannelDataStore  data=(ChannelDataStore)channel.ChannelData;
                                      
foreach(string uri in data.ChannelUris)
                               
{
                                              Console.WriteLine(
" Url :"+uri);
                                         }

                        }

           2.      注册已经定义好的通道到Remoting中。
                      ChannelServices.RegisterChannel(channel);
      
           3.      激活(注册)远程对象类型,使用类RemotingConfiguration      

                     RemotingConfiguration.RegisterWellKnownServiceType
                       (
typeof(Hello),  //类型,远程对象的类
                       "Hi"//URL
                       WellKnownObjectMode.SingleCall); //MODE模式

客户端:  先注册一通道,接着激活远程对象的代理对象(这和服务器注册的对象的有关的
                   使用其 准确的URL和端口号),最后就可以用产生的代理类进行调用远程的方法             

                     ChannelServices.RegisterChannel(new TcpClientChannel());
                      
//创建代理类,并使用Activator进行激活,产生一个代理对象
                     Hello obj=(Hello)Activator.GetObject
                     (
typeof(Hello),    //远程对象类类
                      "tcp://localhost:8086/Hi"); 
                       
//协议,服务器名(或IP)、URL、端口,URL也就是服务器上写明的
                     
//格式为 protocol://server:port/url

                  或者:使用RemotingConfiguration类来进行激活,但不返回对象          

                    RemotingConfiguration.RegisterWellKnownClientType
                         (
typeof(Hello),  //类型,远程对象的类
                        "Hi"//URL
                         WellKnownObjectMode.SingleCall); //MODE模
                         Hello obj=new Hello();          //实例

                  使用Activator类下方法GetOjbect()在对象方法完成之后就小毁了, 而Activator下方法
                  CreateInstance()可以指定使用时间,也就是租借时间.这样必须引用类
                  System.Runtime.Remoting.Activation.UrlAttribute                  

             bject[] arlat={newUrlAttribute("tcp://localhost:8086/Hi")};
                 ojectHandle handle
=Activator.CreateInstance
                 (
"RemotingHello",//程序集的名称,也就是DLL
                "RemotingHello.Hello"//创建名称指定的类型事例也就是引用的类
               urlat);
               Hello  obj
=(Hello)handle.Unwrap();//返回被包装的对象

                 修改租借时间,重写远程对象的MarshalByRefObject类下方法InitializeLifetimeService()
               

                  //重新写租借的默认时间情况
               public override object InitializeLifetimeService()
                 
{
                             ILease lease
=(ILease)base.InitializeLifetimeService();
                             
//租借10分
                              lease.InitialLeaseTime=TimeSpan.FromMinutes(10);
                              lease.RenewOnCallTime
=TimeSpan.FromSeconds(40);
                             
return lease;         
                         }



 

posted on 2006-08-23 17:17  pursuedream  阅读(264)  评论(0)    收藏  举报