XRPC之接口双向调用

栏目: IT技术 · 发布时间: 4年前

内容简介:一般远程接口调用的服务都是基于客户端主动调用服务端,由服务端来提供相关的接口服务;在新版本的组件提供两个包分别是:组件是以接口作为基础通讯单元,所以必须以接口的方式来描述服务调用逻辑。接下来实现一个简单的接口,客户端向服务调用注册方法,服务端在接受客户注册后创建一个会话代理并调用获取客户端的时间。接口定义如下:

一般远程接口调用的服务都是基于客户端主动调用服务端,由服务端来提供相关的接口服务;在新版本的 XRPC 中引入了一个新的功能,即接口双向通讯,组件提供服务创建客户会话的接口代理并调用客户提供的接口服务。接下来介绍如何通过 XRPC 来使用接口双向通讯的应用,并实现服务端调用 WFP/WINFROM 这些客户端的本地方法。

引用组件

组件提供两个包分别是: BeetleX.XRPCBeetleX.XRPC.Clients ;前者是在 .net core 上使用,而后者则提供给 WFP/WINFROM 使用.在 0.8.2.3 版本开始支持接口双向调用功能。

使用

组件是以接口作为基础通讯单元,所以必须以接口的方式来描述服务调用逻辑。接下来实现一个简单的接口,客户端向服务调用注册方法,服务端在接受客户注册后创建一个会话代理并调用获取客户端的时间。接口定义如下:

    public interface IUser
    {
        Task Login(string name);

        Task<DateTime> GetTime();
    }

接口比较简单分别是 LoginGetTime ,接下来会分别在服务端和客户端实现这一接口,并进行一个双向调用。

服务端实现

    [Service(typeof(IUser))]
    public class Program : IUser
    {
        static void Main(string[] args)
        {
            var builder = new HostBuilder()
            .ConfigureServices((hostContext, services) =>
            {
                services.UseXRPC(s =>
                {
                    s.ServerOptions.LogLevel = BeetleX.EventArgs.LogType.Warring;
                    s.ServerOptions.DefaultListen.Port = 9090;
                    s.RPCOptions.ParameterFormater = new JsonPacket();//default messagepack
                },
                    typeof(Program).Assembly);
            });
            builder.Build().Run();
        }

        public Task<DateTime> GetTime()
        {
            return DateTime.Now.ToTask();
        }

        public Task Login(string name)
        {
            Console.WriteLine($"{name} login");
            var token = XRPCServer.EventToken;
            Task.Run(async () =>
            {
                IUser user = token.Server.GetClient<IUser>(token.Session);
                while (true)
                {
                    var time = await user.GetTime();
                    Console.WriteLine($"{name}[{token.Session.RemoteEndPoint}] time is:{time}");
                    //await Task.Delay(1000);
                }
            });
            return Task.CompletedTask;
        }
    }

代码比较简单,在登陆方法中创建一个异步方法,并在方法中创建一个 IUser 针对当前会话的一个代理,然后循环调用客户端方法获取相应的时间。

客户端实现

    class Program : IUser
    {
        static XRPCClient client;
        static void Main(string[] args)
        {
            client = new XRPCClient("192.168.2.18", 9090);
            client.PingTimeout = 5;
            client.Options.ParameterFormater = new JsonPacket();
            client.Register<IUser>(new Program());
            var user = client.Create<IUser>();
            user.Login("henry");
            System.Threading.Thread.Sleep(-1);
        }

        public Task<DateTime> GetTime()
        {
            return Task.FromResult(DateTime.Now);
        }

        public Task Login(string name)
        {
            return Task.CompletedTask;
        }
    }

比起服务端,客户端所需要的代码就更简单了;通过 XRPCClient.Create 注册相关接口的本地实现类。只要客户端调用 user.Login("henry"); 后服务端就是不停地向客户获取时间。通过运行程序可以看到以下运行结果:

XRPC之接口双向调用

以上完整代码可以从以下连接获取: https://github.com/IKende/BeetleX-Samples/tree/master/XRPC.InterfaceTwoWay

聊天服务

上面已经描述了接口双向调用的便利性,接下来通过接口双向调用快速地实现一个聊天服务。

    public interface IUser
    {
        Task Login(string name);

        Task Talk(string name, string message);

        Task Exit(string name);
    }

以上是一个用户聊天的行为接口,分别是登陆、退出和发送消息。接下来通过服务端和客户端实现这一接口即可完成一个简单的聊天服务。

服务端实现

    [EventNext.Service(typeof(IUser))]
    public class UserImpl : IUser
    {
        public Task Exit(string name)
        {
            return Task.CompletedTask;
        }

        public Task Login(string name)
        {
            var token = XRPCServer.EventToken;
            token.Session.Name = name;
            foreach (var session in token.Server.Server.GetOnlines())
            {
                if (!string.IsNullOrEmpty(session.Name))
                {
                    IUser user = token.Server.GetClient<IUser>(session);
                    user.Login(name);
                }
            }
            return Task.CompletedTask;
        }

        public Task Talk(string name, string message)
        {
            var token = XRPCServer.EventToken;
            if (string.IsNullOrEmpty(token.Session.Name))
            {
                throw new Exception("登陆无效!");
            }
            foreach (var session in token.Server.Server.GetOnlines())
            {
                if (!string.IsNullOrEmpty(session.Name))
                {
                    IUser user = token.Server.GetClient<IUser>(session);
                    user.Talk(session.Name, message);
                }
            }
            return Task.CompletedTask;
        }
    }

服务端主要实现了两个方法,分别是登陆和发送消息;两个方法的都基本一样,在方法调用里面获取所有会话的 IUser 代理,并执行相关方法即可。为什么 Exit 这个方法没有实现呢,主要是服务通过监听连接断开事件进行处理,代码如下:

        static void Main(string[] args)
        {
            var builder = new HostBuilder()
            .ConfigureServices((hostContext, services) =>
            {
                services.UseXRPC(s =>
                {
                    s.ServerOptions.LogLevel = BeetleX.EventArgs.LogType.Debug;
                    s.ServerOptions.DefaultListen.Port = 9090;
                    s.RPCOptions.ParameterFormater = new JsonPacket();//default messagepack
                    s.RPCDisconnect += (o, e) =>
                    {
                        foreach (var session in e.Server.GetOnlines())
                        {
                            if (session != e.Session && !string.IsNullOrEmpty(session.Name))
                            {
                                IUser user = s.GetClient<IUser>(session);
                                user.Exit(e.Session.Name);
                            }
                        }
                    };
                },
                    typeof(Program).Assembly);
            });
            builder.Build().Run();
        }

这样一个简单的聊天服务就完成,接下来看一下客户端同样实现这一接口来完成功能。

客户端实现

    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window, IUser
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        public Task Login(string name)
        {
            AddMessage(name, "login");
            return Task.CompletedTask;
        }
        public Task Exit(string name)
        {
            AddMessage(name, "exit");
            return Task.CompletedTask;
        }
        public Task Talk(string name, string message)
        {
            AddMessage(name, message);
            return Task.CompletedTask;
        }
        private BeetleX.XRPC.Clients.XRPCClient mClient;
        private IUser mUser;
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            mClient = new BeetleX.XRPC.Clients.XRPCClient("192.168.2.18", 9090);
            mClient.Options.ParameterFormater = new JsonPacket();
            mClient.Register<IUser>(this);
            mUser = mClient.Create<IUser>();
            txtMessages.Document.Blocks.Clear();
        }
        private async void CmdLogin_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(txtName.Text))
                {
                    MessageBox.Show("请输入登录名称!");
                    return;
                }
                await mUser.Login(txtName.Text);
                MessageBox.Show("登陆成功!");
            }
            catch (Exception e_)
            {
                MessageBox.Show(e_.Message);
            }
        }
        private async void CmdTalk_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                await mUser.Talk(null, txtTalk.Text);
            }
            catch (Exception e_)
            {
                MessageBox.Show(e_.Message);
            }
        }
    }

以上是一个 WPF 窗体的实现,代码功能是不是很简单,通过远程方法调用,服务端可以直接调用客户端窗体的方法代码。接下来看一下实际运行效果:

XRPC之接口双向调用

这样一个简单了聊天服务就完成了,看上去是不是非常简单;如果需要下载示例的完整代码可以访问: https://github.com/IKende/BeetleX-Samples/tree/master/XRPC.WFPChat

通过接口双向调用的功能,你可以实现更简单的通讯应用开发,因为你再也不需要定义消息标记来区分处理行为,可以大大地提高开发效率。


以上所述就是小编给大家介绍的《XRPC之接口双向调用》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

人人都在说谎

人人都在说谎

赛思·斯蒂芬斯--达维多维茨 / 胡晓姣、张晨、左润男 / 中信出版集团 / 2018-11 / 58

有多少人买了书真正看完了? 你朋友的酒量有他说的那么大吗? 父母是否暗自喜欢男孩儿多于女孩儿? 电影里暴力镜头增多会导致犯罪率升高吗? 种族歧视在现如今的美国还严重吗? 特朗普的胜利有征兆吗,什么促成他赢得了大选? …… 你知道问题的答案吗,直觉会怎样告诉你? 作者赛思·斯蒂芬斯--达维多维茨是一位前谷歌数据科学家和专栏作家。他的研究发现,世界充满了......一起来看看 《人人都在说谎》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具