.Net Remoting
应用程序域
应用程序域提供一个托管环境,.Net 程序集都运行在应用程序域上。一个进程中可包含多个应用程序域,但只能有一个默认程序域,同一进程下的应用程序域独立运行。通过图查看 系统进程、应用程序域、.Net CLR.
.Net Remoting
.Net Remoting 提供了一种允许对象通过应用程序域与另一应用程序域对象进行交互的框架。因应用程序域在进程中,其实实现了不同进程的对象通信,或不同计算机的对象通信。实现了客户端可以创建使用远程对象。 简而言之,我们可以将其看作是一种分布式处理方式。
.Net Remoting 实现部分
.Net Remoting 由三部分组成
- 代理(Proxy)客户端通过代理和服务端进行交互
- 格式器(Formatter) 传递的消息序列化,内置 Binary与SOAP序列化
- 通道(Channel)客户端与服务端通信的通道 Http(Http协议通信)、 tcp(tcp协议)、 ipcc(同一电脑不同进程)
两种传送方式 - 传值封送:服务端实例化对象并传递消息,客户端接受消息后对消息反序列化,并在客户端创建实体,代理指向客户端实体。 (一般对数据传值封送,对象要求可序列化)
传引用封送 服务端实例化对象并传递消息,客户端接受消息后对消息反序列化,但客户端不创建实体,代理指向客户端实体。每次调用代理发生消息服务端执行并返回。
传引用封送分为三种激活方式- 客户端注册 服务端为每个客户端代理创建一个单独的对象。
- 服务端 Singleton 服务端只创建几个对象
服务端 SingleCall 服务端对每次请求创建,而每次返回后销毁(无状态 类似http协议)
***
这里用书中的例子进行讲解。ServerAssembly
服务类库程序集,ServerAssembly
服务端控制台程序ClientConsole
客户端控制台程序 都需要引用ServerAssembly
和System.Runtime.Remoting
(在.Net FrameWork 2.0下).服务端
ServerAssembly
服务类
public class DemoClass : MarshalByRefObject { private int count = 0; public DemoClass() { Console.WriteLine("\n----DomoClass Constructor---"); } public void ShowCount(string name) { count++; Console.WriteLine("{0},the counts {1}", name, count); } public void ShowAppDomain() { AppDomain currentDomain = AppDomain.CurrentDomain; Console.WriteLine(currentDomain.FriendlyName); } public int GetCount() { return count; } }
ServerAssembly
服务端控制台程序class Program { static void Main(string[] args) { RegisterChannel(); RemotingConfiguration.ApplicationName = "SimpleRemote"; ServerActivatedSingleCall(); ServerActivatedSingleton(); ClientActivated(); Console.WriteLine("Service begin"); Console.ReadKey(); } //1.通道注册,循环监听客户端请求 private static void RegisterChannel() { //tcp channel IChannelReceiver tcpChnl = new TcpChannel(8501); ChannelServices.RegisterChannel(tcpChnl, false); //http channel IChannel httpChnl = new HttpChannel(8502); ChannelServices.RegisterChannel(httpChnl, false); } //2 注册三种激活方式 // client activated object private static void ClientActivated() { Console.WriteLine("way: client activated object"); Type t = typeof(DemoClass); RemotingConfiguration.RegisterActivatedServiceType(t); } // server singlecall private static void ServerActivatedSingleCall() { Console.WriteLine("Way server activated singlecall"); Type t = typeof(DemoClass); RemotingConfiguration.RegisterWellKnownServiceType(t, "ServerSingleCall", WellKnownObjectMode.SingleCall); } //server singleton private static void ServerActivatedSingleton() { Console.WriteLine("Way server activated singleton"); Type t = typeof(DemoClass); RemotingConfiguration.RegisterWellKnownServiceType(t, "ServerSingleton", WellKnownObjectMode.Singleton); } }
ClientConsole
客户端控制台程序class Program { static void Main(string[] args) { ClientActivated(); RunTest("CAO1"); RunTest("CAO2"); Console.WriteLine("Client running"); Console.ReadKey(); } private static void RunTest(string objectName) { // 2 代理 DemoClass obj = new DemoClass(); obj.ShowAppDomain(); obj.ShowCount(objectName); Console.WriteLine("{0} the count is {1}", objectName, obj.GetCount()); obj.ShowCount(objectName); Console.WriteLine("{0} the count is {1}", objectName, obj.GetCount()); } // 1 三种激活方式,客户端只用一种 // client activated object private static void ClientActivated() { Console.WriteLine("way: client activated object"); Type t = typeof(DemoClass); string url = "tcp://127.0.0.1:8501/SimpleRemote"; RemotingConfiguration.RegisterActivatedClientType(t, url); } // server singlecall private static void ServerActivatedSingleCall() { Console.WriteLine("Way server activated singlecall"); Type t = typeof(DemoClass); string url = "tcp://127.0.0.1:8501/SimpleRemote/ServerSingleCall"; RemotingConfiguration.RegisterWellKnownClientType(t, url); } //server singleton private static void ServerActivatedSingleton() { Console.WriteLine("Way server activated singleton"); Type t = typeof(DemoClass); string url = "tcp://127.0.0.1:8501/SimpleRemote/ServerSingleton"; RemotingConfiguration.RegisterWellKnownClientType(t, url); } }
分离服务程序集
代码客户端应引用ServerAssembly
服务类程序集(泄露隐私)。两种方式- 接口分类 客户端引用一个
ServerAssembly
程序集类似的接口,需要注意接口不可实例化Activator.getobject()
空类 创建一个
ServerAssembly
程序集,方法实现为空(可以借助soapsuds.exe)。回调
回调为,服务端调用客户端。将两个角色反转,实现双工,这里不再举例