c# Remoting通信的步骤和问题

…衆ロ難τιáo~ 提交于 2019-12-15 07:08:17

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双向通信(三)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!