浅谈.net remoting 与webservice
下图是.NET Remoting的体系结构图 .NET Remoting通信体系结构 一般来说,.NET Remoting包括如下几点主要元素: 消息在信道上的传递过程 ? 消息接受器:如上图所示,消息接受器在服务器端和客户端都有,接受真实代理的调用,把序列化的消息发布到信道上。 ? 激活器:这涉及到对象生命期管理,客户机使用激活器在服务器上创建远程对象,或者说是申请一个远程对象的引用。 ? RemotingConfiguration类:该类用于配置远程服务器和客户机的一个实用类,它可以用于读取配置文件或者动态地配置远程对象。说明一点的是:RemotingConfiguration类中的大部分属性、方法都是静态的,这就意味着很多属性,如应用程序名称,只能通过当前属性或配置文件设置一次。如果应用程序运行在宿主环境中,例如 Internet 信息服务 (IIS),则可能已经设置了该值(通常将其设置为虚拟目录)。如果未设置应用程序名称,则当前属性将返回空引用。 ? ChannelServices类:该类用于注册信道,并把消息分派到信道上。 下面写一个.NET Remoting 的示例程序,示例工程的结构如下: 其中,ClassLibrary是远程对象的类库,Client、Server是控制台程序。 ClassLibrary代码如下: using System;
namespace ClassLibrary1
{
public class Class1:MarshalByRefObject
{
public Class1()
: base()
{
Console.WriteLine("远程对象被创建!");
}
~Class1()
{
Console.WriteLine("远程对象被析构!");
}
public void SayHello(string name)
{
Console.WriteLine("你好,{0}",name);
}
public int GetSomthing(string s)
{
if (s!=null)
{
Console.WriteLine("我执行了!");
return s.Length;
}
return -1;
}
}
}
相关说明如下: 1.远程对象的创建 客户端在获取服务器端对象时,并不是获得实际的服务端对象,而是获得它的引用。因此在Remoting中,对于远程对象有一些必须的定义规范要遵循。 由于Remoting传递的对象是以引用的方式,因此所传递的远程对象类必须继承MarshalByRefObject。MSDN对MarshalByRefObject的说明是:MarshalByRefObject 是那些通过使用代理交换消息来跨越应用程序域边界进行通信的对象的基类。不是从 MarshalByRefObject 继承的对象会以隐式方式按值封送。当远程应用程序引用一个按值封送的对象时,将跨越远程处理边界传递该对象的副本。因为您希望使用代理方法而不是副本方法进行通信,因此需要继承MarshallByRefObject。 需要注意的是Class1继承自MarshalByRefObject类,即声明为远程对象。关于MarshalByRefObject具体请参考MSDN。 Server的代码如下: using System;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting;
using ClassLibrary1;
namespace Server
{
class Program
{
/// <summary>
/// 服务端应用
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
//利用TCP通道,并侦听12345端口
TcpServerChannel channel = new TcpServerChannel(12345);
ChannelServices.RegisterChannel(channel,true);
//使用WellKnown激活方式,并且使用SingleCall模式
RemotingConfiguration.RegisterWellKnownServiceType(typeof(Class1),"Class1",WellKnownObjectMode.SingleCall);
Console.Read();
}
}
}
相关说明如下: 1、Remoting的两种通道 Remoting的通道主要有三种:Tcp和Http和IPC。在.Net中,System.Runtime.Remoting.Channel中定义了IChannel接口。IChannel接口包括了TcpChannel通道类型和Http通道类型。它们分别对应Remoting通道的前两种类型。 TcpChannel类型放在名字空间System.Runtime.Remoting.Channel.Tcp中。Tcp通道提供了基于Socket的传输工具,使用Tcp协议来跨越Remoting边界传输序列化的消息流。TcpChannel类型默认使用二进制格式序列化消息对象,因此它具有更高的传输性能。HttpChannel类型放在名字空间 System.Runtime.Remoting.Channel.Http中。它提供了一种使用Http协议,使其能在Internet上穿越防火墙传输序列化消息流。默认情况下, HttpChannel类型使用Soap格式序列化消息对象,因此它具有更好的互操作性。IPC不需要通道,适合本机使用,速度可想而知,比Tcp和Http都要快。 通常在局域网内,我们更多地使用TcpChannel;如果要穿越防火墙,则使用HttpChannel。服务端和客户端在同一台主机上,优先考虑IPC。 2、远程对象的激活方式 在访问远程类型的一个对象实例之前,必须通过一个名为Activation的进程创建它并进行初始化。这种客户端通过通道来创建远程对象,称为对象的激活。在Remoting中,远程对象的激活分为两大类:服务器端激活和客户端激活。 (1)服务器端激活,又叫做WellKnow方式,很多又翻译为知名对象。为什么称为知名对象激活模式呢?是因为服务器应用程序在激活对象实例之前会在一个众所周知的统一资源标识符(URI)上来发布这个类型。然后该服务器进程会为此类型配置一个WellKnown对象,并根据指定的端口或地址来发布对象。.Net Remoting把服务器端激活又分为SingleTon模式和SingleCall模式两种。 SingleTon模式:此为有状态模式。如果设置为SingleTon激活方式,则Remoting将为所有客户端建立同一个对象实例。当对象处于活动状态时,SingleTon实例会处理所有后来的客户端访问请求,而不管它们是同一个客户端,还是其他客户端。SingleTon实例将在方法调用中一直维持其状态。举例来说,如果一个远程对象有一个累加方法(i=0;++i),被多个客户端(例如两个)调用。如果设置为SingleTon方式,则第一个客户获得值为1,第二个客户获得值为2,因为他们获得的对象实例是相同的。如果熟悉Asp.Net的状态管理,我们可以认为它是一种Application状态。 SingleCall模式:SingleCall是一种无状态模式。一旦设置为SingleCall模式,则当客户端调用远程对象的方法时,Remoting会为每一个客户端建立一个远程对象实例,至于对象实例的销毁则是由GC自动管理的。同上一个例子而言,则访问远程对象的两个客户获得的都是1。我们仍然可以借鉴Asp.Net的状态管理,认为它是一种Session状态。 (2)客户端激活。与WellKnown模式不同,Remoting在激活每个对象实例的时候,会给每个客户端激活的类型指派一个URI。客户端激活模式一旦获得客户端的请求,将为每一个客户端都建立一个实例引用。SingleCall模式和客户端激活模式是有区别的:首先,对象实例创建的时间不一样。客户端激活方式是客户一旦发出调用的请求,就实例化;而SingleCall则是要等到调用对象方法时再创建。其次,SingleCall模式激活的对象是无状态的,对象生命期的管理是由GC管理的,而客户端激活的对象则有状态,其生命周期可自定义。其三,两种激活模式在服务器端和客户端实现的方法不一样。尤其是在客户端,SingleCall模式是由GetObject()来激活,它调用对象默认的构造函数。而客户端激活模式,则通过CreateInstance()来激活,它可以传递参数,所以可以调用自定义的构造函数来创建实例。 Client的代码如下: using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels;
using ClassLibrary1;
namespace Client {
class Program {
static void Main(string[] args)
{
try
{
//使用TCP通道连接
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel,true);
//获取远程对象
Class1 class1 = (Class1)Activator.GetObject(typeof(Class1),"tcp://localhost:12345/Class1");
//调用远程对象的方法
class1.SayHello("DebugLZQ");
class1.SayHello("http://www.cnblogs.com/DebugLZQ");
int i=class1.GetSomthing("DebugLZQ");
Console.WriteLine("输入的长度是,{0}",i);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message );
}
Console.Read();
}
}
}
程序的运行结果如下: Client端运行结果: 小结:Microsoft .NET Remoting 提供了一种允许对象通过应用程序域与另一对象进行交互的框架。也就是说,使用.NET Remoting,一个程序域可以访问另外一个程序域中的对象,就好像这个对象位于自身内部,只不过,对这个远程对象的调用,其代码是在远程应用程序域中进行的,例如在本地应用程序域中调用远程对象上一个会弹出对话框的方法,那么,这个对话框,则会在远程应用程序域中弹出。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |