XRPC接口双向调用

一般远程接口调用的服务都是基于客户端主动调用服务端,由服务端来提供相关的接口服务;在新版本的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");后服务端就是不停地向客户获取时间。通过运行程序可以看到以下运行结果:

以上完整代码可以从以下连接获取: 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 messagepacks.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窗体的实现,代码功能是不是很简单,通过远程方法调用,服务端可以直接调用客户端窗体的方法代码。接下来看一下实际运行效果:

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/312401.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电机控制pid_微电机控制如此简单,揭秘微电机调速的控制,PID控制之双环调速...

​​在微型电机应用中&#xff0c;由于各种应用产品的不同会用到不同的调速方式&#xff0c;在调速中可能会遇到各种不同的问题&#xff0c;下面天孚电机对最近客户对微电机PID调速遇到的双环控制问题来讲一讲。智能小车TFMOTOR-N30减速电机​客户是做智能小车的采用的是tfn30微…

简单的01背包和完全背包

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 01背包&#xff08;每种物品只能使用一次&#xff09;&#xff1a; //Wecccccccc //2020.12.31 #include <iostream> using namespace std; int n,m,v[1010],w[1010],dp[1010]; int…

图片上传组件_配置Django-TinyMCE组件 实现上传图片功能

Django自带的Admin后台&#xff0c;好用&#xff0c;TinyMCE作为富文本编辑器&#xff0c;也蛮好用的&#xff0c;这两者结合起来在做博客的时候很方便&#xff08;当然博客可能更适合用Markdown来写&#xff09;&#xff0c;但是Django-TinyMCE这个组件默认没有图片上传功能的…

.NET Core 3.1之深入源码理解HealthCheck(二)

写在前面前文讨论了HealthCheck的理论部分&#xff0c;本文将讨论有关HealthCheck的应用内容。可以监视内存、磁盘和其他物理服务器资源的使用情况来了解是否处于正常状态。运行状况检查可以测试应用的依赖项&#xff08;如数据库和外部服务终结点&#xff09;以确认是否可用和…

多重背包问题以及二进制优化

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 多重背包问题&#xff08;N< 100): //Wecccccccc //2020.12.31 #include <iostream> using namespace std; int n,m,dp[110]; int main() {cin>>n>>m;for(int i0;i&…

UnitTest in .NET(Part 2)

Photo &#xff1a;Unit Test in Visual Studio文 | Edison Zhou上一篇我们学习基本的单元测试基础知识和入门实例。但是&#xff0c;如果我们要测试的方法依赖于一个外部资源&#xff0c;如文件系统、数据库、Web服务或者其他难以控制的东西&#xff0c;那又该如何编写测试呢&…

二维费用的背包问题

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 //Wecccccccc //2020.12.31 #include <iostream> using namespace std; int n, v, m, dp[120][120];int main() {cin >> n >> v >> m;for (int i 0; i < n; i) …

UnitTest in .NET(Part 1)

Photo &#xff1a;Unit Test in Visual Studio文 | Edison Zhou2015年看了Roy Osherove的《单元测试的艺术》一书&#xff0c;颇有收获。因此&#xff0c;我在当时就将我的学习笔记过程记录了下来&#xff0c;并分为四个部分分享成文&#xff0c;与各位Share。本篇作为入门&am…

找出一个字符串中出现次数最多的字_Day34:第一个只出现一次的字符

剑指Offer_编程题——第一个只出现一次的字符题目描述&#xff1a;在一个字符串(0<字符串长度<10000&#xff0c;全部由字母组成)中找到第一个只出现一次的字符&#xff0c;并返回它的位置&#xff0c;如果没有则返回-1&#xff0c;需要区分大小写。(从0开始计数)。具体要…

2020 WTM 继续向前

WTM3.1 正式发布在过去的2019年&#xff0c;承蒙各位的厚爱&#xff0c;WTM从零开始一年的时间在GitHub上收获了将近1600星&#xff0c;nuget上的下载量累计超过10万。WTM所坚持的低码开发&#xff0c;快速实现的理念受到了越来越多.netcore使用者的喜爱。在2020年&#xff0c;…

使用ASP.NET Core 3.x 构建 RESTful API - 4.3 HTTP 方法的安全性和幂等性

什么样的HTTP方法是安全的&#xff1f; 如果一个方法不会改变资源的表述&#xff0c;那么这个方法就被认为是安全的。 例如 HTTP GET 和 HTTP HEAD 就被认为是安全的&#xff0c;但需要注意的是&#xff0c;这并不意味着执行GET请求就不会引起其它的资源操作&#xff0c;在表面…

混合背包问题

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 //Wecccccccc //2020.12.31 #include <iostream> using namespace std; #include <vector>struct note {int kind;int v, w; };vector <note> kinds; int n, v, v1, w, dp…

.NET Core 3.1通用主机原理及使用

一、前言只是讲asp.net core 3.x通用主机的大致原理&#xff0c;这些东西是通过查看源码以及自己根据经验总结得来的&#xff0c;在文章中不会深入源码&#xff0c;因为个人觉得懂原理就晓得扩展点&#xff0c;后期碰到有需求的时候再仔细去研究源码也不迟。阅读前你应该先去了…

火焰效果材质实现_「游戏开发」使用Unity实现魔法火焰效果

*本文转载自公众号“Unity官方平台”。本文由视觉效果艺术家Evgeny Starostin分享如何使用Unity制作魔法火焰效果的过程&#xff0c;让我们一起学习和制作魔法火焰吧。下面是魔法火焰效果图。项目下载本文提供项目工程及着色器下载。本文为转载文章&#xff0c;请关注公众号“U…

激光炸弹(二维前缀和问题)

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 //Wecccccccc //2021.1.2 #include <iostream> using namespace std; const int N 5010; int mp[N][N]; int main() {int n,m,k,r,x,y,w;cin>>k>>r;r min(r,5001);n m …

错误使用.Net Redis客户端CSRedisCore,自己挖坑自己填

本文2019年中原创首发于博客园&#xff0c;当时使用CSRedisCore的排障思路引起很大反响&#xff0c;当时被张队公众号翻牌&#xff0c;本次转回公号。背景上次Redis MQ分布式改造之后&#xff0c;编排的容器稳定运行一个多月&#xff0c;昨天突然收到ETL端同事通知&#xff0c;…

最佳牛围栏(二分)

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 #include <iostream> using namespace std; #include <algorithm> const int N 100001; int n, m; int cow[N]; double sum[N];bool check (double ave) {for (int i 1; i <…

IHostingEnvironment VS IHostEnvironment - .NET Core 3.0中的废弃类型

原文&#xff1a;https://andrewlock.net/ihostingenvironment-vs-ihost-environment-obsolete-types-in-net-core-3/作者&#xff1a;Andrew Lock译者&#xff1a;Lamond Lu本篇是如何升级到ASP.NET Core 3.0系列文章的第二篇。Part 1 - 将.NET Standard 2.0 类库转换为.NET C…

【敏捷案例】老板太外行,朝令夕改!要不要拿了年终奖就撤?

快到春节了&#xff0c;不知道有多少人在等着春节后跳槽&#xff0c;想跳槽的原因也很多&#xff0c;其中一个比较普遍的原因是和老板聊不到一块儿去。前两天&#xff0c;有个学员咨询了我们一个问题&#xff0c;因为这个问题比较普遍&#xff0c;拿出来和大家一起讨论一下~提出…

【2019总结篇】谈谈数字化时代,ERP如何坐稳数字化底座

源宝导读&#xff1a;面向未来&#xff0c;信息化、在线化、智能化&#xff0c;开放应该是数字化转型的核心要素&#xff01;本文将重点介绍2019年明源云ERP开放平台在推进数字化转型中的核心技术层面的实践成果。一、前言面向未来&#xff0c;信息化、在线化、智能化&#xff…