remoting的概念:(1)在服务端建立一个类A,并var a = new A()实例化运行,客户端可以通话remoting获取到这个对象a的代理,然后在本地使用a,就好像于a运行在客户端,其实是运行在服务端的,调用a内的方法,返回的也是服务器对象a内的运行结果。也就是可以远程获取或者改变服务器内的变量。
(2)可以通过在服务端定义事件,在客户端订阅(+=)的方式实现服务器在需要客户端响应的时候,客户端可以响应。swap类的解释:客户端不能为类a添加事件的实现方法,因为类a是在服务端运行的,实现方法也必须在服务端,所以多建了一个类swap。
Swap交换类同样继承了 MarshalByRefObject,说明它也可以跨程序域。如果客户订阅定事件的时候先订阅到Swap的对象上,然后Swap的事件才被客户端订阅,这样就利用一个交换机制实现了订阅。因为在订阅Swap的时候,服务器发现自己本地也有Swap,所以它可以找到,而这个Swap对象又恰恰是在客户端实例化的,所以Swap的对象也可以订阅客户端的事件。
使用步骤:(1)建立类A并生成A1.dll
public delegate void Dtext1(string str);//自定义委托
public class A1 : MarshalByRefObject //必须继承此类
{
public override object InitializeLifetimeService()//必须有这个方法
{
return null;
}
public event Dtext1 Etext1; //自定义事件
public void text1(string str)//服务端需要客户端响应的时候执行此方法
{
if (Etext1!= null)
{
Delegate[] del_list = Etext1.GetInvocationList();
foreach (Delegate del in del_list)
{
var t = new Thread(() =>
{
var d1 = (Dtext1)del;
d1.BeginInvoke(str, null, null);//如果委托没有参数,只填两个null
})
{ IsBackground = true };
t.Start();
}
}
}
public class Swap : MarshalByRefObject
{
public override object InitializeLifetimeService()
{
return null;
}
public event Dtext1 Etext1;
public void tEtext1(string str)
{
Etext1?.Invoke(str);
}
}
(2)服务端代码,需要几个引用
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using A1;
static void Main(string[] args)
{
BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
IDictionary idic = new Dictionary<string, int>();
idic["port"] = 1234;//使用remoting需要使用端口,客户端代码要连接这个端口,端口自定义
TcpChannel tcpchannel = new TcpChannel(idic, clientProvider, serverProvider);
ChannelServices.RegisterChannel(tcpchannel, false);
//实例化并建立代理
var a = new A1();
ObjRef objRef = RemotingServices.Marshal(a , "url001");
Console.ReadLine();
}
(3)客户端代码,需要的引用和服务端一样
public A1 a;
private void Form1_Load(object sender, EventArgs e)
{
BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
IDictionary idic = new Dictionary<string, int>();
idic["port"] = 0;
IChannel channel1 = new TcpClientChannel("client001", new BinaryClientFormatterSinkProvider());
ChannelServices.RegisterChannel(channel1, false);
//获取服务端a的代理
a= (A1)Activator.GetObject(typeof(A1), "tcp://服务端ip:1234/url001");
Swap swap = new Swap();
a.Etext1+= new Dtext1(swap.tEtext1);
swap.Etext1+= new Dtext1(text1);
}
public void text1(string str)
{
//客户端自己的实现逻辑
}
问题:测试的结果是在外网服务端不能触发客户端注册的事件
博友连接:
初探Remoting双向通信(三)
来源:CSDN
作者:AndroidLittle
链接:https://blog.csdn.net/qq_35226440/article/details/103470653