一般远程接口调用的服务都是基于客户端主动调用服务端,由服务端来提供相关的接口服务;在新版本的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

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

XRPC接口双向调用相关推荐

  1. Go 学习笔记(35)— Go 接口 interface (接口声明、接口初始化、接口方法调用、接口运算、类型断言、类型查询、空接口)

    1. 接口概念 接口是双方约定的一种合作协议.接口实现者不需要关心接口会被怎样使用,调用者也不需要关心接口的实现细节.接口是一种类型,也是一种抽象结构,不会暴露所含数据的格式.类型及结构. 接口内部存 ...

  2. java跨域权重_爱站权重查询 API 接口请求调用

    原标题:爱站权重查询 API 接口请求调用 爱站权重查询 API 接口在网上已经很多且大都封装成了 API 供别人调用.支持前台跨域请求,以GET/POST方式提交即可.爱站权重查询 API 接口可以 ...

  3. COM 组件设计与应用(十一)—— IDispatch 及双接口的调用

    原文:http://www.vckbase.com/index.php/wv/1236 一.前言 前段时间,由于工作比较忙,没有能及时地写作.其间收到了很多网友的来信询问和鼓励,在此一并表示感谢.咳. ...

  4. 查找这个接口的调用_事务处理不当,线上接口又双叒内存泄漏了!(附图解问题全过程)...

    情景 项目上线了一个接口,先灰度一台机器观察调用情况: 接口不断的调用,过了一段时间,发现机器上的接口调用开始报 OOM异常 ! 当天就是上线deadline了,刺激.. 发现问题 第一步,使用 jp ...

  5. 第三方快递接口API调用

    更多面试题请狠狠的点击 下载 快递鸟接口API调用案例,因时间仓促,没有申请EBusinessID和APPkey,申请id和替换: 接口文档及各开发语言Demo <

  6. promise设置多个接口并行调用

    promise如何设置多个接口并行调用呢?这里我使用了promise all的方式,一开始让三个接口同时调用,代码如下图所示. mounted: function () {this.$nextTick ...

  7. 抖音sdk接口API调用-关注与取消关注抖音号

    抖音sdk接口API调用-关注与取消关注抖音号 /**      * @author wechat:happybabby110      * @blog http://www.wlkankan.cn ...

  8. 支付宝支付之“单笔转账到支付宝账户接口”的调用(生成签名、上传应用公钥、下载SDK、接口调用、报错自动排查、查看错误码)

    支付宝接口调用 "单笔转账到支付宝账户"的接口调用,一般涉及到下面几个知识点 1.生成签名 在使用支付宝接口的时候,需要使用支付宝的签名,这里需要使用支付宝的RSA生成工具. 关于 ...

  9. IDEA中报错:java: -source 1.5 中不支持静态接口方法调用

    用到java的一些新特性的时候,必须是在新的java版本中才能体现出来,否则会报错. 例如使用java8的Stream流或者lambadas特性,就会报如下错误: **Error:(11, 35) j ...

最新文章

  1. mysql高可用_mysql高可用方案
  2. ArrayList的实现原理--转
  3. 释放tcp连接的命令是_最实用的6个网络命令,网络故障不求人
  4. i茅台app上线首日,直接冲到了App Store免费榜第一
  5. 通过JavaScript获取查询字符串的值
  6. playframework 打包在tomcat里部署
  7. STM32 资料整理贴
  8. 如何用Python画一只机器猫?| 原力计划
  9. 拓端tecdat|R语言样条曲线、分段线性回归模型piecewise regression估计个股beta值分析收益率数据
  10. 人工智能生物学深度解析,附源代码
  11. java读取修改文件内容_JAVA读取文件指定内容进行修改
  12. 2020首届海洋目标智能感知国际挑战赛 冠军方案分享
  13. 好斗or炒作?甲骨文“撕咬”过的那些对手 - 爱上英语题库系统|郭雄飞
  14. 页面浏览pdf或图片iframe
  15. 红旗Linux网卡Bind,请教一下在红旗linux中安装网卡RTL8168/8111的问题
  16. CSS线性渐变和径向渐变详解
  17. python列表get方法_Python json.get方法代码示例
  18. 转发:IT行业中的甲方乙方关系
  19. 【阅读】当我遇见一个人
  20. 3.Single Image Dehazing via MSCNN-HE 论文阅读

热门文章

  1. 二值图像--形态学处理3 开操作和闭操作
  2. 什么是Adobe Lightroom,我需要它吗?
  3. [PHP] 多表外连接性能测试及优化
  4. SSIS 执行变量中的脚步输出列顺序与SQL查询列顺序不同
  5. 十五天精通WCF——第十一天 如何对wcf进行全程监控
  6. 51CTO下载专题有奖征集建议:您的期待,我们的方向!
  7. WPF 实现展示反应盘、者试剂仓控件
  8. 2022版Win11重磅升级!
  9. Win11安卓极速教程!
  10. C#10,带来了Date和Time类型