.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
版权声明:本文为博主原创文章,转载请附上博文链接!


少有人走的路


















