Remoting简单测试

好几年没用过Remoting了,15年之前还经常用,现在直接用WebSocket或者TCP、UDP了,同事使用Remoting遇到点问题,使用他的Demo测试,总结一下吧。

看看百度百科对Remoting的解释:

在Remoting中是通过通道(channel)来实现两个应用程序和域之间对象的通信的。首先,客户端通过Remoting,访问通道以获得服务端对象,再通过代理解析为客户端对象。这就提供一种可能性,即以服务的方式来发布服务器对象。远程对象代码可以运行在服务器上(如服务器激活的对象和客户端激活的对象),然后客户端再通过Remoting连接服务器,获得该服务对象并通过序列化在客户端运行。在Remoting中,对于要传递的对象,设计者除了需要了解通道的类型和端口号之外,无需再了解数据包的格式。这既保证了客户端和服务器端有关对象的松散耦合,同时也优化了通信的性能。

https://baike.baidu.com/item/Remoting/769587?fr=aladdin

跳坑总结:服务端及客户端通信的对象尽量写在一个共享库中,即使分开使用定义,一定要注意:

  • 两端对象的命名空间、类名必须写成一致
  • 对象属性定义可有差异,比如属性个数可以不同,但相互调用的属性定义必须一致:访问修饰符、属性类型、属性名称等。

一句话:命名空间、类定义尽量一致

下面给出测试例子:

Remoting简单测试

1. RemoteObject.cs

服务端与客户端通信对象,尽量放在一个共享库中,需要继续MarshalByRefObject类

using System;
using System.Collections.Generic;

namespace MessageObject
{
    public class RemoteObject : MarshalByRefObject
    {
        public static Queue<string> qMessage { get; set; }

        public string SendMessage(string message)
        {
            if (qMessage == null)
            {
                qMessage = new Queue<string>();
            }
            qMessage.Enqueue(message);
            return message;
        }
    }
}

2. 服务端测试代码

单独建立一个控制台工程,引入带有上面通信对象的共享库,注册Remoting通道,开启Remoting服务,等待客户端调用。

using MessageObject;
using System;
using System.Collections.Generic;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Threading;

namespace IPCServer
{
    class Program
    {
        static void Main(string[] args)
        {
            StartServer();
            Thread thread = new Thread(new ThreadStart(ReceviceMessage));
            thread.Start();
        }

        private static void StartServer()
        {
            IpcServerChannel channel = new IpcServerChannel("ServerChannel");
            ChannelServices.RegisterChannel(channel, false);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteObject), "RemoteObject", WellKnownObjectMode.SingleCall);
            Console.WriteLine("消息服务启动...");
        }

        private static void ReceviceMessage()
        {
            while (true)
            {
                Queue<string> qMessage = RemoteObject.qMessage;
                if (qMessage != null)
                {
                    if (qMessage.Count > 0)
                    {
                        string message = qMessage.Dequeue();
                        Console.WriteLine("接收消息是:" + message);
                    }
                }
                Thread.Sleep(1000);
            }
        }
    }
}

3. 客户端测试代码

单独建立一个客户端测试控制台工程,连接服务端Remoting服务,调用服务端通信对象,达到访问服务端的目的

using MessageObject;
using System;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;

namespace IPCClient
{
    class Program
    {
        static void Main(string[] args)
        {
            RemoteObject objRemoteObject = ConnectServer();
            Send(objRemoteObject);
        }

        private static void Send(RemoteObject objRmoteObject)
        {
            while (true)
            {
                Console.WriteLine("请输入消息...");
                string message = Console.ReadLine();
                try
                {
                    objRmoteObject.SendMessage(message);
                    Console.WriteLine("发送成功");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"无法连接到消息服务:{ex.Message}");
                }
            }
        }
        private static RemoteObject ConnectServer()
        {
            IpcClientChannel channel = new IpcClientChannel();
            ChannelServices.RegisterChannel(channel, false);
            RemoteObject objRemoteObject = (RemoteObject)Activator.GetObject(typeof(RemoteObject), "ipc://ServerChannel/RemoteObject");
            return objRemoteObject;
        }
    }
}

通信对象如果必须放在两个不同的解决方案或者工程中,当客户端无法访问服务端远程对象时,比如提示:“连接到 IPC 端口失败: 系统找不到指定的文件。”,可使用此demo测试:

  • 服务端是否先于客户端开启?
  • 尝试检查两端通信对象命名空间一致吗?比如服务端远程对象命令空间定义为:namespace MessageObjectServer,客户端为:namespace MessageObjectClient,这样肯定不行的
  • 通信使用的属性定义相同吗?比如都要使用这个属性:public static Queue qMessage { get; set; },服务端定义为Queue<string>,客户端定义为List<string>,这样也是不行的。

总结完毕。

除非注明,文章均由 Dotnet9 整理发布,欢迎转载。

转载请注明:
作者:Dotnet9
链接:https://dotnet9.com/6861.html
来源:Dotnet9
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

发表评论

登录后才能评论