一,remoting基础
一种分布式处理方式,可以说是DCOM的一种升级
跨过应用程序域,与另外的应用程序域进行通信,即穿越边界
在remoting中是通过通道(channel)来实现两个应用程序域之间对象的通信的
优缺点:
优点:
1、能让我们进行分布式开发
2、Tcp通道的Remoting速度非常快
3、虽然是远程的,但是非常接近于本地调用对象
4、可以做到保持对象的状态
5、没有应用程序限制,可以是控制台,winform,iis,windows服务承载远程对象
缺点:
1、非标准的应用因此有平台限制
2、脱离iis的话需要有自己的安全机制
两种通道:
1,Tcp
2,Http
System.Runtime.Remoting.Channel中定义了IChannel接口。IChannel接口包括了TcpChannel通道类型和Http通道类型
TcpChannel类型放在名字空间System.Runtime.Remoting.Channel.Tcp中。Tcp通道提供了基于Socket的 传输工具,使用Tcp协议来跨越Remoting边界传输序列化的消息流。TcpChannel类型默认使用二进制格式序列化消息对象,因此它具有更高的 传输性能
HttpChannel类型放在名字空间System.Runtime.Remoting.Channel.Http中。它提供了一种使用Http协议, 使其能在Internet上穿越防火墙传输序列化消息流。默认情况下,HttpChannel类型使用Soap格式序列化消息对象,因此它具有更好的互操 作性
通常在局域网内,我们更多地使用TcpChannel;如果要穿越防火墙,则使用HttpChannel。
远程对象的激活方式
客户通过通道来创建远程对象,成为对象的激活。
remoting远程激活
1,服务端激活(Wellknow又翻译为知名对象) 两种方式: 1,SingleTon模式
2,SingleCall模式
2,客户端激活
服务端激活:
SingleTon模式:此为有状态模式。如果设置为SingleTon激活方式,则Remoting将为所有客户端建立同一个对象实例。当对象处于活动 状态时,SingleTon实例会处理所有后来的客户端访问请求,而不管它们是同一个客户端,还是其他客户端。SingleTon实例将在方法调用中一直 维持其状态
SingleCall模式:SingleCall是一种无状态模式。一旦设置为SingleCall模式,则当客户端调用远程对象的方法时,Remoting会为每一个客户端建立一个远程对象实例,至于对象实例的销毁则是由GC自动管理的。
举例说明:一个方法(i=0,++i)
SingleTon模式,第一个客户端调用得到1,而第二个得到2,依次类推.....
SingleCall模式,多个客户端调用都得到1.
客户端激活:与WellKnown模式不同,Remoting在激活每个对象实例的时候,会给每个客户端激活的类型指派一个URI。客户端激活模式一旦获得客户端的请求,将为每一个客户端都建立一个实例引用。
二远程对象的定义:
remoting传递对象的方式:引用方式
必须继承:MarshalByRefObject(使用代理交换消息来跨越应用程序域边界进行通信的对象的基类)
下面我们定义一个远程对象:
创建一个类库项目:
代码如下:
public class ServerObject : MarshalByRefObject//如不继承将会报此错误:尝试创建未绑定类型的代理 { public Car GetCarMessage(string carname, string carcolor, int carprice) { Car car = new Car(); car.CarName = carname; car.Carcolor = carcolor; car.Carprice = carprice; return car; } }
[Serializable] public class Car { public Car() { } private string carname;//车名 private string carcolor;//颜色 private int carprice;//价格 public string CarName { get { return carname; } set { carname = value; } } public string Carcolor { get { return carcolor; } set { carcolor = value; } } public int Carprice { get { return carprice; } set { carprice = value; } } }
OK,远程对象定义完成,编译生成ServeObject.dll
三,服务器端
新建一个控制台应用程序
注册通道:
注册Channel
注意引用:System.Runtime.Remoting.dll ServerObject.dll
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;//注册TcpChannel时引用
using System.Runtime.Remoting.Channels.Http;//注册HttpChannel时引用
using ServerObject;
注册远程对象
服务端激活(两种模式)
WellKnownObjectMode.SingleCall 每个传入的消息由新的对象实例提供服务
WellKnownObjectMode.Singleton 每个传入的消息由同一个对象实例提供服务
客户端激活(见代码)
public class CarServer { [STAThread] public static void Main(string[] args) { TcpServerChannel channel = new TcpServerChannel(8088);//注册TcpChannel
//HttpServerChannel channel = new HttpServerChannel(8089);//注册HttpChannel bool ensureSecurity = false;//确保安全 ChannelServices.RegisterChannel(channel, ensureSecurity);
//服务端激活 RemotingConfiguration.RegisterWellKnownServiceType(typeof(ServerObject.ServerObject), "Hi", WellKnownObjectMode.SingleCall);//SingleCall模式
//RemotingConfiguration.RegisterWellKnownServiceType(typeof(ServerObject.ServerObject), "Hi", WellKnownObjectMode.Singleton );//Singleton 模式
//客户端激活
//RemotingConfiguration.ApplicationName = "Hi"; RemotingConfiguration.RegisterActivatedServiceType(typeof(ServerObject.ServerObject)); System.Console.WriteLine("正在运行....."); System.Console.ReadLine(); } }
注销通道:
如果要关闭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); } }
四,客户端
注册通道:(见代码注释);
获得对象:(见代码注释);
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using System.Runtime.Remoting.Channels.Http; using ServerObject; namespace RemotingClientTest { public class CarClient { public static void Main(string[] args) { TcpChannel channel = new TcpChannel(); //HttpChannel channel = new HttpChannel(); ChannelServices.RegisterChannel(channel, false); // ChannelServices.RegisterChannel(new TcpClientChannel(), false);当然这样写也是一样的。TcpClientChannel和TcpChannel基本是一样的(个人理解) //获得远程对象 //服务端激活 ServerObject.ServerObject obj = (ServerObject.ServerObject)Activator.GetObject(typeof(ServerObject.ServerObject), "tcp://10.18.1.232:8088/Hi");//WellKnown激活模式 tcp通道 //ServerObject.ServerObject obj = (ServerObject.ServerObject)Activator.GetObject(typeof(ServerObject.ServerObject), "Http://10.18.1.232:8088/Hi");//WellKnown激活模式 Http通道 //客户端激活 // RemotingConfiguration.RegisterActivatedClientType(typeof(ServerObject.ServerObject), "tcp://10.18.1.232:8088/Hi"); //ServerObject.ServerObject serverObj = new ServerObject.ServerObject(); //方法二:调用进程Activator的CreateInstance()方法(略) if (obj == null) { Console.WriteLine("could not locate server"); return; } for (int i = 0; i < 5; i++) { Car car= obj.GetCarMessage("宝马","蓝色",1000000); Console.WriteLine(car.CarName + car.Carcolor + car.Carprice); Console.ReadKey(); } } } }
五,运行效果
服务端:
客户端:
OK,初学者写的可能有很多不足,还请多多指教!