.net Remoting是.NET自带的一种RPC调用方式。主要解决多个进程间互相的调用。
建立一个公用的对象,该对象在服务端声明并共享出去,各个进程可以取到这个公共的对象,并修改该对象。
如希望实现一个进程调用另一个进程,那么使用代理来实现该目的。
TCP连接效率较快,但是基本只能用于本机。HTTP效率较慢,但是可以用于局域网。注意,服务端和客户端必须使用相同的协议。
下面是一个演示:
进程13196做为客户端访问做为服务端的进程10840。
经过实验,可以看到ipc方式最快,而tcp方式在第一次的时候延迟了几秒,后面调用就快了。也许是tcp需要三次握手?
下面是RemotingHelper类库代码:
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.Serialization.Formatters; using System.Text; using System.Threading.Tasks; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using System.Runtime.Remoting.Channels.Ipc; namespace WindowsFormsApplication1 { /// <summary> /// Remoting工具类 /// </summary> public class RemotingHelper { public enum ChannelType { Tcp=0,Ipc } private static RemotingHelper _remoting = new RemotingHelper(); protected RemotingHelper() { } /// <summary> /// 服务端tcp信道句柄 /// </summary> private TcpServerChannel _tcpServerChannel; /// <summary> /// 客户端tcp信道句柄 /// </summary> private TcpClientChannel _tcpClientChannel; /// <summary> /// 服务端ipc信道句柄 /// </summary> private IpcServerChannel _ipcServerChannel; /// <summary> /// 客户端ipc信道句柄 /// </summary> private IpcClientChannel _ipcClientChannel; private void InitServer(int port, bool singleton) { //初始化参数 var serverProvider = new BinaryServerFormatterSinkProvider(); serverProvider.TypeFilterLevel = TypeFilterLevel.Full; IDictionary props = new Hashtable(); props["name"] = "RemoteObject"; props["port"] = port; props["typeFilterLevel"] = TypeFilterLevel.Full; //注册tcp信道 var tcpChannel = new TcpServerChannel(props, serverProvider); _tcpServerChannel = tcpChannel; ChannelServices.RegisterChannel(tcpChannel, false); //下面是注册远程对象 if (singleton) { //单例模式 RemotingConfiguration.RegisterWellKnownServiceType( typeof(RemoteObject), "RemoteObject", WellKnownObjectMode.Singleton); } else { //实例模式 RemotingConfiguration.RegisterWellKnownServiceType( typeof(RemoteObject), "RemoteObject", WellKnownObjectMode.SingleCall); } //注册ipc信道 var ipcChannel = new IpcServerChannel("testIpc"); _ipcServerChannel = ipcChannel; ChannelServices.RegisterChannel(ipcChannel, false); if (singleton) { //单例模式 RemotingConfiguration.RegisterWellKnownServiceType( typeof(RemoteObject), "SenData", WellKnownObjectMode.Singleton); } else { //实例模式 RemotingConfiguration.RegisterWellKnownServiceType( typeof(RemoteObject), "SenData", WellKnownObjectMode.SingleCall); } } /// <summary> /// 注销服务 /// </summary> private void UnregisterChannel() { if (_tcpClientChannel != null) { _tcpServerChannel.StopListening(null); ChannelServices.UnregisterChannel(_tcpServerChannel); } if (_ipcClientChannel != null) { _ipcServerChannel.StopListening(null); ChannelServices.UnregisterChannel(_ipcServerChannel); } } /// <summary> /// 连接服务,取得运程对象 /// </summary> /// <param name="port"></param> /// <param name="server"></param> /// <returns></returns> private IRemoteObject Connect(int port, ChannelType ctype, string server = "localhost") { if (ctype == ChannelType.Tcp) { _tcpClientChannel = new TcpClientChannel(); ChannelServices.RegisterChannel(_tcpClientChannel, false); var remoteObject = (IRemoteObject)Activator.GetObject(typeof(RemoteObject), $"tcp://{server}:{port}/RemoteObject"); return remoteObject; } else { _ipcClientChannel = new IpcClientChannel(); ChannelServices.RegisterChannel(_ipcClientChannel, false); var remoteObject = (IRemoteObject)Activator.GetObject(typeof(RemoteObject), $"ipc://testIpc/SenData"); return remoteObject; } } /// <summary> /// 客户端断开连接 /// </summary> private void Disconnect() { if (_tcpClientChannel != null) { try { ChannelServices.UnregisterChannel(_tcpClientChannel); } finally { _tcpClientChannel = null; } } if (_ipcClientChannel != null) { try { ChannelServices.UnregisterChannel(_ipcClientChannel); } finally { _ipcClientChannel = null; } } } /// <summary> /// 启动服务 /// </summary> /// <param name="singleton"></param> /// <param name="port"></param> public static void StartServer(bool singleton = true, int port = 12345) { _remoting.InitServer(port, singleton); } /// <summary> /// 停止服务 /// </summary> public static void StopServer() { _remoting.UnregisterChannel(); } /// <summary> /// 连接运程服务 /// </summary> /// <param name="port"></param> /// <param name="ctype">信道类型</param> /// <returns></returns> public static IRemoteObject ConnectServer(ChannelType ctype, int port = 12345) { return _remoting.Connect(port, ctype); } /// <summary> /// 客户端断开连接 /// </summary> public static void DisconnectServer() { _remoting.Disconnect(); } } /// <summary> /// 远程对象接口 /// </summary> public interface IRemoteObject { /// <summary> /// 接口定义 /// </summary> /// <param name="request"></param> /// <returns></returns> RemotingResponse Factorial(RemotingRequest request); } /// <summary> /// 运程对象类 /// </summary> public class RemoteObject : MarshalByRefObject, IRemoteObject { public RemotingResponse Factorial(RemotingRequest request) { Console.WriteLine("Received Message:" + request.Message); var repliedMessage = $"服务进程={Process.GetCurrentProcess().Id}" + $"服务类型:{RemotingConfiguration.GetRegisteredWellKnownServiceTypes()[0].Mode}" + $"Replay:{request.Message}"; return new RemotingResponse(repliedMessage) { Result = Factorial(request.Factorial) }; } private int Factorial(int n) { if (n > 1) { return n * Factorial(n - 1); } else { return 1; } } } /// <summary> /// 请求参数 /// </summary> [Serializable] public class RemotingRequest { public int Factorial { get; set; } public string Message { get; set; } } public enum RetCode { t1, t2 } /// <summary> /// 返回信息类 /// </summary> [Serializable] public class RemotingResponse { /// <summary> /// 返回码:枚举类型 /// </summary> public RetCode code { get; private set; } /// <summary> /// 计算结果 /// </summary> public decimal Result { get; set; } public string Message { get; private set; } public RemotingResponse(string msg) { Message = msg; } } }
下面是winform代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using WindowsFormsApplication1; namespace WindowsFormsApp1 { public partial class Form1 : Form { IRemoteObject rmo = null; protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); Text = $"进程ID= {Process.GetCurrentProcess().Id.ToString()}"; txtSendMsg.Text = Text; } public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } private void btnStartServer_Click(object sender, EventArgs e) { RemotingHelper.StartServer(rbSingleton.Checked); } private void btnStopServer_Click(object sender, EventArgs e) { RemotingHelper.StopServer(); } private void btnLinkService_Click(object sender, EventArgs e) { var s1 = RemotingHelper.ChannelType.Tcp; if (rbIpc.Checked) s1 = RemotingHelper.ChannelType.Ipc; rmo = RemotingHelper.ConnectServer(s1); } private void btnDisconnect_Click(object sender, EventArgs e) { RemotingHelper.DisconnectServer(); rmo = null; } private void btnSendMsg_Click(object sender, EventArgs e) { var factorial = int.Parse(txtN.Text); var msg = txtSendMsg.Text; var rep = rmo.Factorial(new RemotingRequest() { Factorial = factorial, Message = msg }); txtCalResult.Text = $"{factorial}!={rep.Result}"; MessageBox.Show(this, $"{factorial}!={rep.Result}", rep.Message); } } }
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

