.net Remoting用TCP和HTTP区别(上)

2010年04月04日 星期日 11:08
Remoting和WebService都是.Net提供的远程访问的方法,Remoting具有以下几个优点

1、Tcp通道的Remoting速度非常快
2、虽然是远程的,但是非常接近于本地调用对象
3、可以做到保持对象的状态
4、没有应用程序限制,可以是控制台,winform,iis,windows服务承载远程对象
缺点:
1、不是标准的应用,因此有平台限制
2、脱离iis的话需要有自己的安全机制

BB)remoting和web服务的区别?
    asp.net web 服务基础结构通过将 soap 消息映射到方法调用,为 web 服务提供了简单的 api。通过提供一种非常简单的编程模型(基于将 soap 消息交换映射到方法调用),它实现了此机制。asp.net web 服务的客户端不需要了解用于创建它们的平台、对象模型或编程语言。而服务也不需要了解向它们发送消息的客户端。唯一的要求是:双方都要认可正在创建和使用 的 soap 消息的格式,该格式是由使用 wsdl 和 xml 架构 (xsd) 表示的 web 服务合约定义来定义的。
    . net remoting 为分布式对象提供了一个基础结构。它使用既灵活又可扩展的管线向远程进程提供 .net 的完全对象语义。asp.net web 服务基于消息传递提供非常简单的编程模型,而 .net remoting 提供较为复杂的功能,包括支持通过值或引用传递对象、回调,以及多对象激活和生命周期管理策略等。要使用 .net remoting,客户端需要了解所有这些详细信息,简而言之,需要使用 .net 建立客户端。.net remoting 管线还支持 soap 消息,但必须注意这并没有改变其对客户端的要求。如果 remoting 端点提供 .net 专用的对象语义,不管是否通过 soap,客户端必须理解它们。

相对而言,Remoting更适合于中小型局域网应用,而不适用于企业级的应用,WebService更适合后者。

创建一个Remoting应用的大致步骤:

【1】创建共享类库,即Remoting对象,其中包含所要Remottable的类,继承自System.MarshalByRefObject对象,编译成DLL。

public class ResumeLoader : System.MarshalByRefObject 
{
 public ResumeLoader()
 {
  System.Console.WriteLine("New Referance Added!");
}
public Resume GetResumeByUserID(decimal userID)
 {
return new Resume(1);
 }
}
【2】创建服务器对象。
1.注册通道
2.注册远程对象
类似与以下代码
//注册通道
TcpChannel chan=new TcpChannel(8085);
   ChannelServices.RegisterChannel(chan);
   //注册提供服务的远程对象
   RemotingConfiguration.RegisterWellKnownServiceType(typeof( ResumeLoader)," ResumeLoader
",WellKnownObjectMode.Singleton);
【3】创建Remoting客户端程序
1.注册通道,
客户端实例化通道
2.获取远程对象
【4】 在客户端使用new来产生代理:
ResumeLoader rc = new ResumeLoader ();

         
-----------------------------------------------------------------------------------------------------------------------------

一 什么是 .Net Remoting?

简而言之,我们可以将其看作是一种分布式处理方式。从微软的产品角度来看,可以说 Remoting就是DCOM的一种升级,它改善了很多功能,并极好的融 合到.Net平台下。Microsoft® .NET Remoting 提供了一种允许对象通过应用程序域与另一对象进行交互的框架。

二如何实现通信

在Remoting中是通过通道(channel)来实现两个应用程序域之间对象的通信的。

1、Remoting的两种通道 Tcp和Http 在.Net中,System.Runtime.Remoting.Channel中定义了IChannel接口。IChannel接口包括了 TcpChannel通道类型和Http通道类型。它们分别对应Remoting通道的这两种类型。对比如下:

Tcp Http
TcpChannel HttpChannel
System.Runtime.Remoting.Channel.Tcp System.Runtime.Remoting.Channel.Http
基于 Socket的传输工具,使用Tcp协议来跨越Remoting边界传输序列化的消息流。
TcpChannel类型默认使用二进制格式序列化消息对象
提供 了一种使用Http协议,使其能在Internet上穿越防火墙传输序列化消息流
更高的传输性能 更好的互操作性
局域网内 如果要穿越防火墙,则使用HttpChannel








 

 

 

 

 

 

 

2、远程对象的激活方式

在访问远程类型的一个对象实例之前,必须通过一个名为Activation的进程创建它并进行初始化。这种客户端通过通道来创建远程对象,称为对象的激活。在Remoting中,远程对象的激活分为两大类

服务器端激活(WellKnow) 客户端激活
服务器应用程序在激活对象实例之前会在一个众所周知的统一资源标识符(URI)上来发布这个类型。然后该服务器进程会为此类型配置一个WellKnown对象,并根据指定的端口或地址来发布对象 Remoting在激活每个对象实例的时候,会给每个客户端激活的类型指派一个URI。客户端激活模式一旦获得客户端的请求,将为每一个客户端都建立一个实例引用。
SingleTon模式 :Remoting 将为所有客户端建立同一个对象实例。当对象处于活动状态时,SingleTon实例会处理所有后来的客户端访问请求,而不管它们是同一个客户端,还是其他 客户端。SingleTon实例将在方法调用中一直维持其状态。可以认为它是一种Application状态.
SingleCall模式 :SingleCall是一种无状态模式。一旦设置为SingleCall模式,则当客户端调用远程对象的方法时,Remoting会为每一个客户端建立一个远程对象实例,至于对象实例的销毁则是由GC自动管理的。认为它是一种Session状态
SingleCall模式和客户端激活模式是有区别的:
首先,对象实例创建的时间不一样。客户端激活方式是客户一旦发出调用的请求,就实例化;而 SingleCall则是要等到调用对象方法时再创建。
其次,SingleCall模式激活的对象是无状态的,对象生命期的管理是由GC管理的,而客户端 激活的对象则有状态,其生命周期可自定义。
其三,两种激活模式在服务器端和客户端实现的方法不一样。尤其是在客户端,SingleCall模式是由 GetObject()来激活,它调用对象默认的构造函数。而客户端激活模式,则通过CreateInstance()来激活,它可以传递参数,所以可以 调用自定义的构造函数来创建实例。

三远程对象的定义
         客户端在获取服务器端对象时,并不是获得实际的服务端对象,而是获得它的引用。因此在Remoting中,对于远程对象有一些必须的定义规范要遵循。
         由于Remoting传递的对象是以引用的方式,因此所传递的远程对象类必须继承MarshalByRefObject。MSDN对 MarshalByRefObject的说明是:MarshalByRefObject 是那些通过使用代理交换消息来跨越应用程序域边界进行通信的对象的基类。不是从 MarshalByRefObject 继承的对象会以隐式方式按值封送。当远程应用程序引用一个按值封送的对象时,将跨越远程处理边界传递该对象的副本。因为您希望使用代理方法而不是副本方法 进行通信,因此需要继承MarshallByRefObject。

以下是一个远程对象类的定义:
public class ServerObject:MarshalByRefObject
{
        public Person GetPersonInfo(string name,string sex,int age)
        {
            Person person = new Person();
            person.Name = name;
            person.Sex = sex;
            person.Age = age;
            return person;
        }
}

这个类只实现了最简单的方法,就是设置一个人的基本信息,并返回一个Person类对象。注意这里返回的Person类。由于这里所传递的Person则是以传值的方式来完成的,而Remoting要求必须是引用的对象,所以必须将Person类序列化。

因此,在Remoting中的远程对象中,如果还要调用或传递某个对象,例如类,或者结构,则该类或结构则必须实现串行化Attribute[SerializableAttribute]:
[Serializable]
public class Person
{
        public Person()
        {
           
        }

        private string name;
        private string sex;
        private int age;

        public string Name
        {
            get    {return name;}
            set    {name = value;}
        }

        public string Sex
        {
            get {return sex;}
            set {sex = value;}
        }

        public int Age
        {
            get {return age;}
            set {age = value;}
        }
   }
将该远程对象以类库的方式编译成Dll。这个Dll将分别放在服务器端和客户端,以添加引用。

在Remoting中能够传递的远程对象可以是各种类型 ,包括复杂的DataSet对象,只要它能够被序列化。远程对象也可以包含事件 ,但服务器端对于事件的处理比较特殊.

四 具体实现方式
根据激活模式的不同,通道类型的不同服务器端的实现方式也有所不同。大体上说分为一下三步

 

服务器端

客户端

1、注册通道

tcp通道和http通道除了性能和序列号格式不同外,实现方式是完全相同的。在实例化通道对象时,将端口号作为参数传递。然后再调用静态方法RegisterChannel()来注册该通道对象即可。
A.项目右键添加引用"System.Runtime.Remoting",
B.添加一下名称空间:
        using System.Runtime.Remoting.Channels;
        using System.Runtime.Remoting.Channels.Http;
      / /using System.Runtime.Remoting.Channels.Tcp;
C. 代码如下:
           HttpChannel channel = new HttpChannel(8080);
          //TcpChannel channel = new TcpChannel(8080);
            ChannelServices.RegisterChannel(channel);


TcpChannel channel = new TcpChannel();
ChannelServices.RegisterChannel(channel);

注意在客户端实例化通道时 ,是调用的默认构造函数,即没有传递端口号。事实上,这个端口号是缺一不可的,只不过它的指定被放在后面作为了Uri的一部分。

2、注册远程对象

注册了通道后,要能激活远程对象,必须在通道中注册该对象。根据激活模式的不同,注册对象的方法也不同

(1) SingleTon模式 对于WellKnown对象,可以通过静 态方法RemotingConfiguration.RegisterWellKnownServiceType ()来实现:RemotingConfiguration.RegisterWellKnownServiceType(
                typeof(ServerRemoteObject.ServerObject),
                "ServiceMessage",WellKnownObjectMode.SingleTon);
(2)SingleCall模式 RemotingConfiguration.RegisterWellKnownServiceType(
                typeof(ServerRemoteObject.ServerObject),
                "ServiceMessage",WellKnownObjectMode.SingleCall);
注册对象的方法基本上和SingleTon模式相同,只需要将枚举参数WellKnownObjectMode改为SingleCall就可以了。
(3)客户端激活模式 RemotingConfiguration.ApplicationName = "ServiceMessage";
RemotingConfiguration.RegisterActivatedServiceType(
                typeof(ServerRemoteObject.ServerObject));
为什么要在注册对象方法前设置ApplicationName属性呢?其实这个属性就是该对象的URI。对于WellKnown模式,URI是放在 RegisterWellKnownServiceType()方法的参数中,当然也可以拿出来专门对ApplicationName属性赋值。而 RegisterActivatedServiceType()方法的重载中,没有ApplicationName的参数,所以必须分开。

 

 

2、获得远程对象。

与服务器端相同,不同的激活模式决定了客户端的实现方式也将不同。不过这个区别仅仅是WellKnown激活模式和客户端激活模式之间的区别,而对于SingleTon和SingleCall模式,客户端的实现完全相同。

(1) WellKnown激活模式

要获得服务器端的知名远程对象,可通过Activator进程的GetObject()方法来获得:
ServerRemoteObject.ServerObject serverObj = (ServerRemoteObject.ServerObject)Activator.GetObject(
              typeof(ServerRemoteObject.ServerObject), "tcp://localhost:8080/ServiceMessage");

首先以WellKnown模式激活,客户端获得对象的方法是使用GetObject()。其中参数第一个是远程对象的类型。第二个参数就是服务器端的uri。如果是http通道,自然是用 http://localhost:8080/ServiceMessage 了。因为我是用本地机,所以这里是localhost,你可以用具体的服务器IP地址来代替它。端口必须和服务器端的端口一致。后面则是服务器定义的远程对象服务名,即ApplicationName属性的内容。
(2) 客户端激活模式
如前所述,WellKnown模式在客户端创建对象时,只能调用默认的构造函数,而客户端激活模式则可以通过自定义的构造函数来创建远程对象。

客户端激活模式有两种方法:
1) 调用RemotingConfiguration的静态方法RegisterActivatedClientType()。这个方法返回值为Void,它只是将远程对象注册在客户端而已。具体的实例化还需要调用对象类的构造函数。
RemotingConfiguration.RegisterActivatedClientType(               
                typeof(ServerRemoteObject.ServerObject),
                "tcp://localhost:8080/ServiceMessage");
ServerRemoteObject.ServerObject serverObj = new ServerRemoteObject.ServerObject();

2) 调用进程Activator的CreateInstance()方法。这个方法将创建方法参数指定类型的类对象。它与前面的GetObject()不同的 是,它要在客户端调用构造函数,而GetObject()只是获得对象,而创建实例是在服务器端完成的。CreateInstance()方法有很多个重 载,我着重说一下其中常用的两个。
a、 public static object CreateInstance(Type type, object[] args, object[] activationAttributes);

b、public static ObjectHandle CreateInstance(string assemblyName, string typeName, object[] activationAttribute);

详细参数说明见表后AAA

说明:要使用UrlAttribute,还需要在命名空间中添加:using System.Runtime.Remoting.Activation;

3、注销通道

如果要关闭Remoting的服务,则需要注销通道也可以关闭对通道的监听 。在Remoting中当我们注册通道 的时候,就自动开启了通道的监听 。而如果关闭了对通道的监听 ,则该通道就无法接受客户端的请求 ,但通道仍然存在 ,如果你想再一次注册该通道,会抛出异常。

           //获得当前已注册的通道;
            IChannel[] channels = ChannelServices.RegisteredChannels;

            //关闭指定名为MyTcp的通道;
            foreach (IChannel eachChannel in channels)
            {
                if (eachChannel.ChannelName == "MyTcp")
                {
                    TcpChannel tcpChannel = (TcpChannel)eachChannel;

                    //关闭监听;
                    tcpChannel.StopListening(null);

                    //注销通道;
                    ChannelServices.UnregisterChannel(tcpChannel);
                }
            }
代码中,RegisterdChannel属性获得的是当前已注册的通道。在Remoting中,是允许同时注册多个通道的,这一点会在后面说明。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值