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

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

Server端:


Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsorusing System;
Remoting中在客户端使用自定义的Sponsor
using System.Collections.Generic;
Remoting中在客户端使用自定义的Sponsor
using System.Text;
Remoting中在客户端使用自定义的Sponsor
using System.Collections;
Remoting中在客户端使用自定义的Sponsor
using System.Runtime.Remoting;
Remoting中在客户端使用自定义的Sponsor
using System.Runtime.Remoting.Lifetime;
Remoting中在客户端使用自定义的Sponsor
using System.Runtime.Remoting.Services;
Remoting中在客户端使用自定义的Sponsor
using System.Runtime.Remoting.Channels;
Remoting中在客户端使用自定义的Sponsor
using System.Runtime.Remoting.Channels.Http;
Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor
#endregion
Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor
namespace Server
{
Remoting中在客户端使用自定义的Sponsor    
class Server
{
Remoting中在客户端使用自定义的Sponsor        
static void Main(string[] args)
{
Remoting中在客户端使用自定义的Sponsor            RemotingConfiguration.ApplicationName 
= "SomeServer";
Remoting中在客户端使用自定义的Sponsor            RemotingConfiguration.Configure(
"server.exe.config");
Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor            Console.WriteLine(
"Server started.");
Remoting中在客户端使用自定义的Sponsor            Console.ReadLine();
Remoting中在客户端使用自定义的Sponsor        }

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

Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor    
public class SomeCAO : MarshalByRefObject
{
Remoting中在客户端使用自定义的Sponsor        
public void doSomething()
{
Remoting中在客户端使用自定义的Sponsor            Console.WriteLine(
"SomeCAO.doSomething() is called.");
Remoting中在客户端使用自定义的Sponsor        }

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

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

Remoting中在客户端使用自定义的Sponsor
namespace Client
{
Remoting中在客户端使用自定义的Sponsor    
public class MySponsor : MarshalByRefObject, ISponsor
{
Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor        
public bool doRenewal = true;
Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor        
public TimeSpan Renewal(System.Runtime.Remoting.Lifetime.ILease lease)
{
Remoting中在客户端使用自定义的Sponsor            Console.WriteLine(
"{0} SPONSOR: Renewal() called", DateTime.Now);
Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor            
if (doRenewal)
{
Remoting中在客户端使用自定义的Sponsor                Console.WriteLine(
"{0} SPONSOR: Will renew (10 secs)", DateTime.Now);
Remoting中在客户端使用自定义的Sponsor                
return TimeSpan.FromSeconds(10);
Remoting中在客户端使用自定义的Sponsor            }

Remoting中在客户端使用自定义的Sponsor            
else
{
Remoting中在客户端使用自定义的Sponsor                Console.WriteLine(
"{0} SPONSOR: Won't renew further", DateTime.Now);
Remoting中在客户端使用自定义的Sponsor                
return TimeSpan.Zero;
Remoting中在客户端使用自定义的Sponsor            }

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

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

Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor    
class Client
{
Remoting中在客户端使用自定义的Sponsor        
static void Main(string[] args)
{
Remoting中在客户端使用自定义的Sponsor            String filename 
= "client.exe.config";
Remoting中在客户端使用自定义的Sponsor            RemotingConfiguration.Configure(filename);
Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor            SomeCAO cao 
= new SomeCAO();
Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor            ILease le 
= (ILease)cao.GetLifetimeService();
Remoting中在客户端使用自定义的Sponsor            MySponsor sponsor 
= new MySponsor();
Remoting中在客户端使用自定义的Sponsor            le.Register(sponsor);
Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor            
try
{
Remoting中在客户端使用自定义的Sponsor                Console.WriteLine(
"{0} CLIENT: Calling doSomething()", DateTime.Now);
Remoting中在客户端使用自定义的Sponsor                cao.doSomething();
Remoting中在客户端使用自定义的Sponsor            }

Remoting中在客户端使用自定义的Sponsor            
catch (Exception e)
{
Remoting中在客户端使用自定义的Sponsor                Console.WriteLine(
" -> EX: Timeout in first call\n{0}", e.Message);
Remoting中在客户端使用自定义的Sponsor            }

Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor            Console.WriteLine(
"{0} CLIENT: Sleeping for 5 seconds", DateTime.Now);
Remoting中在客户端使用自定义的Sponsor            Thread.Sleep(
5000);
Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor            
try
{
Remoting中在客户端使用自定义的Sponsor                Console.WriteLine(
"{0} CLIENT: Calling doSomething()", DateTime.Now);
Remoting中在客户端使用自定义的Sponsor                cao.doSomething();
Remoting中在客户端使用自定义的Sponsor            }

Remoting中在客户端使用自定义的Sponsor            
catch (Exception e)
{
Remoting中在客户端使用自定义的Sponsor                Console.WriteLine(
" -> EX: Timeout in second call\n{0}", e.Message);
Remoting中在客户端使用自定义的Sponsor            }

Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor            Console.WriteLine(
"{0} CLIENT: Telling sponsor to stop", DateTime.Now);
Remoting中在客户端使用自定义的Sponsor            sponsor.doRenewal 
= false;
Remoting中在客户端使用自定义的Sponsor            Console.WriteLine(
"{0} CLIENT: Sleeping for 10 seconds", DateTime.Now);
Remoting中在客户端使用自定义的Sponsor            Thread.Sleep(
10000);
Remoting中在客户端使用自定义的Sponsor
Remoting中在客户端使用自定义的Sponsor            
try
{
Remoting中在客户端使用自定义的Sponsor                Console.WriteLine(
"{0} CLIENT: Calling doSomething()", DateTime.Now);
Remoting中在客户端使用自定义的Sponsor                cao.doSomething();
Remoting中在客户端使用自定义的Sponsor            }

Remoting中在客户端使用自定义的Sponsor            
catch (Exception e)
{
Remoting中在客户端使用自定义的Sponsor                Console.WriteLine(
" -> EX: Timeout in third call\n{0}", e.Message);
Remoting中在客户端使用自定义的Sponsor            }

Remoting中在客户端使用自定义的Sponsor            Console.WriteLine(
"Finished Remoting中在客户端使用自定义的Sponsor press <return> to exit");
Remoting中在客户端使用自定义的Sponsor            Console.ReadLine();
Remoting中在客户端使用自定义的Sponsor        }

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

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

相关文章:

  • 2022-12-23
  • 2022-02-23
  • 2022-12-23
  • 2022-01-15
  • 2021-09-29
  • 2021-12-28
  • 2021-11-29
  • 2021-05-23
猜你喜欢
  • 2022-12-23
  • 2021-08-04
  • 2022-01-13
  • 2022-02-03
  • 2022-12-23
  • 2021-06-29
  • 2021-06-28
相关资源
相似解决方案