今天抽了几个小时的时间,通过做了N个程序的方式探索了下remoting!
首先看服务端配置文件
注意<system.runtime.remoting>节点里面内容为remoting配置文件内容!
1、<service> 节点:
1)<activated type="B, A"/> 主要是“声明一个服务器激活类型”,说白点就是要告诉服务器,当服务器启动的时候,A.dll里面的B类(B类名称要求写全,包括命名空间)对外开放!
2)<wellknown mode="Singleton" type="B, A" objectUri="LocalDb.Factory.Manager" /> 同1一个道理,type声明一个服务器激活类型,这里讲下mode,mode包括两个类型Singleton和SingleCall,其中Singleton是每个连接共享一个实例,SingleCall是一个连接分配一个实例,这么说明白了吧?再说的详细点就是:假设B类中有一个方法i++,Singleton模型时第一个连接服务器的客户端的i是1,第二个连接服务器的客户端的i是2,依次类推。而SingleCall模式则不管是第几个连接客户端的i都是1。然后说下objectUri其实就是要指定一个URI,这个URI在客户端配置的时候要用到。
3)有人要问了,activated 和wellknown 都是声明服务器激活类型,那么有啥实质性差别呢?反正我是没找到,自己试出来的!首先说下activated 的模式类型相当于SingleCall的wellknown,但是它与wellknown 有个质的差别在于由客户端连接服务器时就实例化了!而wellknown 是由客户端连接服务器并且调用该类方法时才实例化的!可见activated 要比wellknown在某种程度上浪费了资源,我个人比较看好wellknown,但是用wellknown要给他多分配一个URI,有点麻烦!
2、<channels> 节点:
1)<channel port="8086" ref="tcp">主要用来“配置应用程序用来与远程对象进行通信的信道”port指定端口,ref指定:远程处理提供的三种信道实现--“http”、“tcp”和“ipc”。
2) <formatter ref="soap" typeFilterLevel="Full"/> ref指定格式化程序接收器提供程序模板的 ID,就是传输用到的模式,是soap,binary,还是xml。typeFilterLevel是反序列化的级别,通常都是FULL。
3、<lifetime>节点:希望大家仔细看这里,也是我测试得到的结果,说起来有点费劲!
首先说3个节点的含义:leaseTime初始生存时间 sponsorshipTimeout超时后依然保留多长时间。renewOnCallTime刷新实例时间。这些解释都已经说的很白话了,文词不见得能说明白问题!leaseTime就是你连接到服务器后,服务器不是给你分配个实例吗?那这个实例不是永久生存的,她是有生存周期的,那么过多久他会“死掉”呢?leaseTime决定了一切!注意这个时间是不变的,比方说你设置1H(H:小时,M分钟,S秒),那么1小时后实例就会死亡!我们想下,这么设置是否会出问题呢?1小时,万一我正用着起劲呢,突然要求我重新连接,岂不郁闷?好暂时先画个问号。我们讲renewOnCallTime,renewOnCallTime他会随着时间的推移不断减少,不过一旦有操作,也就是客户端对连接实例有操作,则马上刷新称设置的值。举个例子:假设renewOnCallTime=1H,连接后没操作,10分钟内没操作,renewOnCallTime变为50M,一旦操作了,renewOnCallTime又变为1H。sponsorshipTimeout实例马上死亡后延长的时间。好了,现在回头看那个问号,很简单就被解决掉了,只要一直操作,绝对不会出现实例死亡的!!
接下来看下客户端配置文件
接下来看下客户端配置文件
通过以上的讲解应该一看就会明白了,需要注意的是activated 对应服务器配置的activated ,而wellknown 对应服务器配置中的wellknown。
以下是例子:
服务器端:
<configuration>
<system.runtime.remoting>
<application>
<service>
<wellknown
mode="Singleton"
type="Hello.Hello, Hello"
objectUri="Hell" />
</service>
<service>
<activated type="testDll.test, testDll"/>
</service>
<channels>
<channel port="8086" ref="http">
<serverProviders>
<formatter ref="soap" typeFilterLevel="Full"/>
<formatter ref="binary" typeFilterLevel="Full"/>
</serverProviders>
</channel>
</channels>
<lifetime
leaseTime="1H"
sponsorshipTimeout="5M"
renewOnCallTime="1H"
/>
</application>
</system.runtime.remoting>
</configuration>
<system.runtime.remoting>
<application>
<service>
<wellknown
mode="Singleton"
type="Hello.Hello, Hello"
objectUri="Hell" />
</service>
<service>
<activated type="testDll.test, testDll"/>
</service>
<channels>
<channel port="8086" ref="http">
<serverProviders>
<formatter ref="soap" typeFilterLevel="Full"/>
<formatter ref="binary" typeFilterLevel="Full"/>
</serverProviders>
</channel>
</channels>
<lifetime
leaseTime="1H"
sponsorshipTimeout="5M"
renewOnCallTime="1H"
/>
</application>
</system.runtime.remoting>
</configuration>
代码:
RemotingConfiguration.Configure(
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, false);
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, false);
System.Console.WriteLine("Press Any Key to Exit ! ");
System.Console.ReadLine();
System.Console.ReadLine();
客户端:
<system.runtime.remoting>
<application>
<client url=" http://localhost:8086">
<activated type="testDll.test, testDll"/>
</client>
<application>
<client url=" http://localhost:8086">
<activated type="testDll.test, testDll"/>
</client>
<client>
<wellknown mode="Singleton" type="Hello.Hello, Hello" url=" http://localhost:8086/Hell" />
</client>
<channels>
<serverProviders>
<formatter ref="binary" typeFilterLevel="Full" />
</serverProviders>
<clientProviders>
<formatter ref="binary" />
</clientProviders>
</channels>
</application>
</system.runtime.remoting>
</configuration>
<wellknown mode="Singleton" type="Hello.Hello, Hello" url=" http://localhost:8086/Hell" />
</client>
<channels>
<serverProviders>
<formatter ref="binary" typeFilterLevel="Full" />
</serverProviders>
<clientProviders>
<formatter ref="binary" />
</clientProviders>
</channels>
</application>
</system.runtime.remoting>
</configuration>
代码:
RemotingConfiguration.Configure(
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, false);
testDll.test ts = new testDll.test();
Hello.Hello obj = new Hello.Hello();
if (obj == null)
{
Console.WriteLine("False to Link Server.");
return;
}
Console.WriteLine(obj.HelloWorld("MadRam.neo"));
Console.WriteLine(ts.GetString());
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, false);
testDll.test ts = new testDll.test();
Hello.Hello obj = new Hello.Hello();
if (obj == null)
{
Console.WriteLine("False to Link Server.");
return;
}
Console.WriteLine(obj.HelloWorld("MadRam.neo"));
Console.WriteLine(ts.GetString());
其中用到的两个类库:
namespace testDll
{
public class test : System.MarshalByRefObject
{
public test()
{
Console.WriteLine("test build!");
}
{
public class test : System.MarshalByRefObject
{
public test()
{
Console.WriteLine("test build!");
}
public string GetString()
{
Console.WriteLine("aaa");
return "test";
}
}
}
{
Console.WriteLine("aaa");
return "test";
}
}
}
namespace Hello
{
public class Hello : System.MarshalByRefObject
{
public Hello()
{
Console.WriteLine("Constructor called");
}
{
public class Hello : System.MarshalByRefObject
{
public Hello()
{
Console.WriteLine("Constructor called");
}
~Hello()
{
Console.WriteLine("Destructor called");
}
{
Console.WriteLine("Destructor called");
}
public string HelloWorld(string name)
{
Console.WriteLine("Hello World!");
return "Hi," + name;
}
{
Console.WriteLine("Hello World!");
return "Hi," + name;
}
}
}