.net remoting(一)
一、远程对象
①RemoteHello.csproj 类库项目,程序集名称 RemoteHello ,默认命名空间 Wrox.ProCSharp.Remoting;
②派生自System.MarsshalByRefObject ;
③根据不同的代理方式,需要有不同的构造函数(注意客户端的代码会有注释);
④Hello.cs源文件中的代码如下;
namespace Wrox.ProCSharp.Remoting { public class Hello:MarshalByRefObject { public Hello() { Console.WriteLine("创建Hello"); } public Hello(string name) { Console.WriteLine($"创建 {name}"); } public string Greeting(string name) { Console.WriteLine($"Hello {name}!!!!"); return $"Hello {name}!!!!"; } } }
二、服务端
①tcp、http和ipc三种不同的通讯协议服务端的实现;
②每种通讯协议都支持激活知名对象和激活客户端激活的对象的服务创建方式;
③每种的通讯协议包含的两种对象创建方式同客户端的代理创建方式都是一 一 对应的,例如:服务端使用的是tcp的服务端激活方式,客户端也必须是tcp的服务端激活方式代理创建方式;
④下方代码位于服务控制台项目HelloServer中的Program.cs源文件中;
⑤注意服务项目需要依赖远程对象库;
using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http; using System.Runtime.Remoting.Channels.Ipc; using System.Runtime.Remoting.Channels.Tcp; using Wrox.ProCSharp.Remoting; namespace HelloServer { class Program { static void Main(string[] args) { {// tcp {// 服务端激活(激活知名对象) //var tcpChannel = new TcpServerChannel(8085); //ChannelServices.RegisterChannel(tcpChannel, false); //RemotingConfiguration.RegisterWellKnownServiceType(typeof(Hello), "Hi", WellKnownObjectMode.SingleCall); } {// 激活客户端激活的对象 //var tcpChannel = new TcpServerChannel(8085); //ChannelServices.RegisterChannel(tcpChannel, false); //RemotingConfiguration.ApplicationName = "Hi"; //RemotingConfiguration.RegisterActivatedServiceType(typeof(Hello)); } } {// http {// 服务端激活(激活知名对象) //var httpChannel = new HttpServerChannel(8086); //ChannelServices.RegisterChannel(httpChannel, false); //RemotingConfiguration.RegisterWellKnownServiceType(typeof(Hello), "Hi", WellKnownObjectMode.SingleCall); } {// 激活客户端激活的对象 //var httpChannel = new HttpServerChannel(8086); //ChannelServices.RegisterChannel(httpChannel, false); //RemotingConfiguration.ApplicationName = "Hi"; //RemotingConfiguration.RegisterActivatedServiceType(typeof(Hello)); } } {// ipc 只能用于客户端和服务端在同一操作系统上 {// 服务端激活(激活知名对象) //var ipcChannel = new IpcServerChannel("myIpcPort"); //ChannelServices.RegisterChannel(ipcChannel, false); //RemotingConfiguration.RegisterWellKnownServiceType(typeof(Hello), "Hi", WellKnownObjectMode.SingleCall); } {// 激活客户端激活的对象 var ipcChannel = new IpcServerChannel("myIpcPort"); ChannelServices.RegisterChannel(ipcChannel, false); RemotingConfiguration.ApplicationName = "Hi"; RemotingConfiguration.RegisterActivatedServiceType(typeof(Hello)); } } Console.WriteLine("Press Enter to exit!"); Console.ReadLine(); } } }
三、客户端
①tcp、http和ipc三种不同的通讯协议客户端的实现;
②每种通讯协议都支持激活知名对象(服务端激活)和激活客户端激活的对象的客户端代理创建方式;
③每种的通讯协议包含的两种对象创建方式同客户端的代理创建方式都是一 一 对应的,例如:服务端使用的是tcp的服务端激活方式,客户端也必须是tcp的服务端激活方式代理创建方式;
④下方代码位于服务控制台项目HelloClient中的Program.cs源文件中;
⑤注意服务项目需要依赖远程对象库;
⑥请注意阅读代码的注释,对规则和特性有关键描述;
⑦每种通讯协议的客户端激活代码都实现了三种远程代理创建方式,中间空了一行间隔开,请一定注意;
using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.Runtime.Remoting.Activation; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http; using System.Runtime.Remoting.Channels.Ipc; using System.Runtime.Remoting.Channels.Tcp; using System.Runtime.Remoting.Lifetime; using System.Text; using Wrox.ProCSharp.Remoting; namespace ConsoleApp3 { class Program { static void Main(string[] args) { try { #region tcp {// tcp { // 服务端激活 对象调用后消失 // 只能默认构造函数 //TcpClientChannel tcpClient = new TcpClientChannel(); //ChannelServices.RegisterChannel(tcpClient, false); //Hello obj = (Hello)Activator.GetObject(typeof(Hello), @"tcp://10.0.6.207:8085/Hi"); //if (obj == null) //{ // Console.WriteLine("获取远程代理失败!"); // return; //} //Console.WriteLine(obj.Greeting("tcp1")); } { // 客户端激活 对象持久 //TcpClientChannel tcpClient = new TcpClientChannel(); //ChannelServices.RegisterChannel(tcpClient, false); //object[] attrs = { new UrlAttribute(@"tcp://10.0.6.207:8085/Hi") }; ////程序集 + 类型 + url属性 默认构造方法 //ObjectHandle handle = Activator.CreateInstance("RemoteHello", "Wrox.ProCSharp.Remoting.Hello", attrs); //if (handle == null) //{ // Console.WriteLine("获取远程代理失败!"); // return; //} //Hello obj = handle.Unwrap() as Hello; //Console.WriteLine(obj.Greeting("tcp1")); //TcpClientChannel tcpClient = new TcpClientChannel(); //ChannelServices.RegisterChannel(tcpClient, false); //object[] attrs = { new UrlAttribute(@"tcp://10.0.6.207:8085/Hi") }; //// 类型 + 参数 + url属性 参数位null,默认构造函数 //Hello obj = (Hello)Activator.CreateInstance(typeof(Hello),new object[] {"周静a" }, attrs); //if (obj == null) //{ // Console.WriteLine("获取远程代理失败!"); // return; //} //Console.WriteLine(obj.Greeting("tcp2")); //TcpClientChannel tcpClient = new TcpClientChannel(); //ChannelServices.RegisterChannel(tcpClient, false); //// 注册 //RemotingConfiguration.RegisterActivatedClientType(typeof(Hello), "tcp://10.0.6.207:8085/Hi"); //// 创建 //Hello obj = new Hello("周静"); //if (obj == null) //{ // Console.WriteLine("注册远程代理对象失败!"); // return; //} //Console.WriteLine(obj.Greeting("tcp3")); } } #endregion #region http {// http { // 服务端激活 对象调用后消失 // 只能默认构造函数 //HttpClientChannel httpClient = new HttpClientChannel(); //ChannelServices.RegisterChannel(httpClient, false); //Hello obj = (Hello)Activator.GetObject(typeof(Hello), @"http://10.0.6.207:8086/Hi"); //if (obj == null) //{ // Console.WriteLine("获取远程代理失败!"); // return; //} //Console.WriteLine(obj.Greeting("http1")); } { // 客户端激活 对象持久 //HttpClientChannel httpClient = new HttpClientChannel(); //ChannelServices.RegisterChannel(httpClient, false); //object[] attrs = { new UrlAttribute(@"http://10.0.6.207:8086/Hi") }; ////程序集 + 类型 + url属性 默认构造方法 //ObjectHandle handle = Activator.CreateInstance("RemoteHello", "Wrox.ProCSharp.Remoting.Hello", attrs); //if (handle == null) //{ // Console.WriteLine("获取远程代理失败!"); // return; //} //Hello obj = handle.Unwrap() as Hello; //Console.WriteLine(obj.Greeting("http1")); //HttpClientChannel httpClient = new HttpClientChannel(); //ChannelServices.RegisterChannel(httpClient, false); //object[] attrs = { new UrlAttribute(@"http://10.0.6.207:8086/Hi") }; //// 类型 + 参数 + url属性 参数位null,默认构造函数 //Hello obj = (Hello)Activator.CreateInstance(typeof(Hello), new object[] { "周静a" }, attrs); //if (obj == null) //{ // Console.WriteLine("获取远程代理失败!"); // return; //} //Console.WriteLine(obj.Greeting("http2")); //HttpClientChannel httpClient = new HttpClientChannel(); //ChannelServices.RegisterChannel(httpClient, false); //// 注册 //RemotingConfiguration.RegisterActivatedClientType(typeof(Hello), "http://10.0.6.207:8086/Hi"); //// 创建 //Hello obj = new Hello("周静"); //if (obj == null) //{ // Console.WriteLine("注册远程代理对象失败!"); // return; //} //Console.WriteLine(obj.Greeting("tcp3")); } } #endregion #region ipc {// ipc 服务端和客户端只能在同一操作系统中,不持支跨域 { // 服务端激活 对象调用后消失 // 只能默认构造函数 //IpcClientChannel ipcClient = new IpcClientChannel(); //ChannelServices.RegisterChannel(ipcClient, false); //Hello obj = (Hello)Activator.GetObject(typeof(Hello), @"ipc://myIpcPort/Hi"); //if (obj == null) //{ // Console.WriteLine("获取远程代理失败!"); // return; //} //Console.WriteLine(obj.Greeting("ipc1")); } { // 客户端激活 对象持久 //IpcClientChannel ipcClient = new IpcClientChannel(); //ChannelServices.RegisterChannel(ipcClient, false); //object[] attrs = { new UrlAttribute(@"ipc://myIpcPort/Hi") }; ////程序集 + 类型 + url属性 默认构造方法 //ObjectHandle handle = Activator.CreateInstance("RemoteHello", "Wrox.ProCSharp.Remoting.Hello", attrs); //if (handle == null) //{ // Console.WriteLine("获取远程代理失败!"); // return; //} //Hello obj = handle.Unwrap() as Hello; //Console.WriteLine(obj.Greeting("ipc1")); //IpcClientChannel ipcClient = new IpcClientChannel(); //ChannelServices.RegisterChannel(ipcClient, false); //object[] attrs = { new UrlAttribute(@"ipc://myIpcPort/Hi") }; //// 类型 + 参数 + url属性 参数位null,默认构造函数 //Hello obj = (Hello)Activator.CreateInstance(typeof(Hello), new object[] { "周静a" }, attrs); //if (obj == null) //{ // Console.WriteLine("获取远程代理失败!"); // return; //} //Console.WriteLine(obj.Greeting("ipc2")); //IpcClientChannel ipcClient = new IpcClientChannel(); //ChannelServices.RegisterChannel(ipcClient, false); //// 注册 //RemotingConfiguration.RegisterActivatedClientType(typeof(Hello), "ipc://myIpcPort/Hi"); //// 创建 //Hello obj = new Hello("周静"); //if (obj == null) //{ // Console.WriteLine("注册远程代理对象失败!"); // return; //} //Console.WriteLine(obj.Greeting("ipc3")); } } #endregion } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine("Press AnyKey to Exit"); Console.ReadKey(); } } }
四、其他注意事项
① 本次实现只是remoting的简单实现,对初学者学习应该能很省很多事,其他AOP等方面的深度应用请阅读相关书籍,C#高级编程系列的书籍;
② 工程项目是在win10 64操作系统上vs2019中实现验证的,如有错误和疑问,欢迎留言,谢谢!
服务端激活