Remoting中在客户端使用自定义的Sponsor

很是郁闷,本来写好了,修改提交了几次又没了一大半,只好简单地重新写一点了。

我说话比较喜欢简洁,直接看代码吧(例子根据《Advanced .NET Remoting》一书而来):

Server端:

Using directives

namespace Server
{
    
class Server
    
{
        
static void Main(string[] args)
        
{
            RemotingConfiguration.ApplicationName 
= "SomeServer";
            RemotingConfiguration.Configure(
"server.exe.config");

            Console.WriteLine(
"Server started.");
            Console.ReadLine();
        }

    }


    
public class SomeCAO : MarshalByRefObject
    
{
        
public void doSomething()
        
{
            Console.WriteLine(
"SomeCAO.doSomething() is called.");
        }

    }

}
因为Sponsor是在Client端,所以采用CAO远程对象,SAO对象的生存期是在Server端管理的。
代码很简单,为了方便测试,用配置文件来实现:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
<system.runtime.remoting>
        
<application>
            
<channels>
                
<channel ref="http" port="5555" >
                    
<serverProviders>
                        
<formatter ref="soap" typeFilterLevel="Full"/>
                    
</serverProviders>
                
</channel>
            
</channels>
      
<lifetime leaseTime="1S" renewOnCallTime="1S" leaseManagerPollTime = "100MS" />
            
<service>
                
<activated type="Server.SomeCAO, Server" />
            
</service>
        
</application>
    
</system.runtime.remoting>
</configuration>
其中
<serverProviders>
    <formatter ref="soap" typeFilterLevel="Full"/>
</serverProviders>
这一段,由于在.NET Framework1.1及之后的版本做了安全限制,所以必须要有,否则在客户端注册Sponsor的时候会有异常。
服务端到此为止,然后是客户端,代码如下:
using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Lifetime;
using System.Threading;
using Server; // from generated_meta.dll

namespace Client
{
    
public class MySponsor : MarshalByRefObject, ISponsor
    
{

        
public bool doRenewal = true;

        
public TimeSpan Renewal(System.Runtime.Remoting.Lifetime.ILease lease)
        
{
            Console.WriteLine(
"{0} SPONSOR: Renewal() called", DateTime.Now);

            
if (doRenewal)
            
{
                Console.WriteLine(
"{0} SPONSOR: Will renew (10 secs)", DateTime.Now);
                
return TimeSpan.FromSeconds(10);
            }

            
else
            
{
                Console.WriteLine(
"{0} SPONSOR: Won't renew further", DateTime.Now);
                
return TimeSpan.Zero;
            }

        }

    }


    
class Client
    
{
        
static void Main(string[] args)
        
{
            String filename 
= "client.exe.config";
            RemotingConfiguration.Configure(filename);

            SomeCAO cao 
= new SomeCAO();

            ILease le 
= (ILease)cao.GetLifetimeService();
            MySponsor sponsor 
= new MySponsor();
            le.Register(sponsor);

            
try
            
{
                Console.WriteLine(
"{0} CLIENT: Calling doSomething()", DateTime.Now);
                cao.doSomething();
            }

            
catch (Exception e)
            
{
                Console.WriteLine(
" -> EX: Timeout in first call\n{0}", e.Message);
            }


            Console.WriteLine(
"{0} CLIENT: Sleeping for 5 seconds", DateTime.Now);
            Thread.Sleep(
5000);

            
try
            
{
                Console.WriteLine(
"{0} CLIENT: Calling doSomething()", DateTime.Now);
                cao.doSomething();
            }

            
catch (Exception e)
            
{
                Console.WriteLine(
" -> EX: Timeout in second call\n{0}", e.Message);
            }


            Console.WriteLine(
"{0} CLIENT: Telling sponsor to stop", DateTime.Now);
            sponsor.doRenewal 
= false;
            Console.WriteLine(
"{0} CLIENT: Sleeping for 10 seconds", DateTime.Now);
            Thread.Sleep(
10000);

            
try
            
{
                Console.WriteLine(
"{0} CLIENT: Calling doSomething()", DateTime.Now);
                cao.doSomething();
            }

            
catch (Exception e)
            
{
                Console.WriteLine(
" -> EX: Timeout in third call\n{0}", e.Message);
            }

            Console.WriteLine(
"Finished  press <return> to exit");
            Console.ReadLine();
        }

    }


}
在激活了远程对象后,使用GetLifetimeService方法获得跟该对象关联的租约对象,然后在该租约上注册一个新创建的我自定义的主办方对象。
在第一次调用远程对象的方法的时候,由于远程对象生存期还没有超时,所以一切正常。第二此调用之前睡眠了5秒。在这期间,远程对象的生存期超时了。所以服务端的租约管理器会询问该对象的所有主办方,看是否有主办方愿意续订租约。这时,客户端的主办方的Renewal方法会被调用,将远程对象生存期加上10秒。这样在第二次调用远程对象方法时也是正常的(在客户端可以看到Renewal方法被调用了)。然后我们把主办方的一个标志置为false,接着睡眠10秒。在这期间,远程对象生存期又会超时,租约管理器同样调用了客户端的主办方的Renewal方法,但是这一次并没有增加远程对象生存期。所以服务端的垃圾回收器会销毁远程对象的租约和对象本身。在接下来的第三次调用远程对象方法时就会产生异常并被捕获了。
客户端的配置文件如下:
<configuration>
  
<system.runtime.remoting>
    
<application>
        
      
<channels>
        
<channel ref="http" port="0" >
                    
<serverProviders>
                        
<formatter ref="soap" typeFilterLevel="Full"/>
                    
</serverProviders>
                
</channel>
      
</channels>
      
<client url="http://localhost:5555/SomeServer" >
              
<activated type="Server.SomeCAO, generated_meta" />
      
</client>
    
</application>
  
</system.runtime.remoting>
</configuration>

最重要的还是
<serverProviders>
    <formatter ref="soap" typeFilterLevel="Full"/>
</serverProviders>
为什么在客户端也需要呢?因为在服务端的租约管理器调用客户端主办方的Renewal方法的过程中,客户端充当了Server的角色,而服务端则扮演了Client的角色,因此在客户端也需要对安全限制做修改。
另外,在编译好服务端项目后,使用Soapsuds工具产生共享程序集:
soapsuds -ia:server -nowp -oa:generated_meta.dll
在客户端项目添加对这个generated_meta.dll的引用,就可以编译成功了。
最后先后运行server和client。结果就是下面这样了:
服务端:
Server started.
SomeCAO.doSomething() is called.
SomeCAO.doSomething() is called.

客户端:
2005-2-23 13:53:08 CLIENT: Calling doSomething()
2005-2-23 13:53:08 CLIENT: Sleeping for 5 seconds
2005-2-23 13:53:10 SPONSOR: Renewal() called
2005-2-23 13:53:10 SPONSOR: Will renew (10 secs)
2005-2-23 13:53:13 CLIENT: Calling doSomething()
2005-2-23 13:53:14 CLIENT: Telling sponsor to stop
2005-2-23 13:53:14 CLIENT: Sleeping for 10 seconds
2005-2-23 13:53:20 SPONSOR: Renewal() called
2005-2-23 13:53:20 SPONSOR: Won't renew further
2005-2-23 13:53:24 CLIENT: Calling doSomething()
 -> EX: Timeout in third call
Requested Service not found
Finished ... press <return> to exit

posted on 2005-02-23 12:08  buaaytt  阅读(1812)  评论(0编辑  收藏  举报

导航