一、遠端物件
①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中實現驗證的,如有錯誤和疑問,歡迎留言,謝謝!
服務端啟用