BeetleX之TCP消息通讯Protobuf/TLS

        在网络通讯应用中直接操作数据流是比较繁琐的事情,毕竟在业务层面处理的都是对象化消息;为了让网络数据操作变得更友好直观,一般都会引用序列化组件来处理网络流和对象之前的转换工作;在这里介绍组件如何使能Protobuf进行数据交互通讯。

协议定义

        组件使用对象处理就不同之前HelloWorld示例一样简单操作流就可以,在这里需要进一步封装一个简单的应用协议。

|-----------------------------------------------------------------|
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7  |
|----------------------------------------------------------------|
|Probobuf数据流长度,占4字节                                      |
|----------------------------------------------------------------|
|Protobuf数据流                                                  |
|----------------------------------------------------------------|

以上是一个简单的应用协议,消息头4字节描述消息的长度,对应长度的数据则是Protobuf序列化对象数据。但这样的协议用在Protobuf上还是有问题,那就是无法知道这些数据对应于那个数据类型对象;所以还需要调整一下

|----------------------------------------------------------------|
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7 |
|----------------------------------------------------------------|
| Probobuf数据流长度,占4字节                                     |
|----------------------------------------------------------------|
| 消息类型,占4字节                                               |
|----------------------------------------------------------------|
| Protobuf数据流                                                 |
|----------------------------------------------------------------|

在序列化数据流前添加了4字节用于描述对应的消息类型,对于这个类型其实可以使用2字节来描述,毕竟一个无符号的短整型可以描述6万多个消息类型了。如果想表达得更友好些可以用字符来描述消息类型,只是字符所占有的空间比较多些。

协议分析器

    组件提供了FixedHeaderPacket抽象协议分析器来处理这种简单应用协议,只要继承重写两个方法即可完成。

    public class ProtobufPacket : FixedHeaderPacket{static ProtobufPacket(){TypeHeaer.Register(typeof(ProtobufPacket).Assembly);}public static CustomTypeHeader TypeHeaer { get; private set; } = new CustomTypeHeader(MessageIDType.INT);public override IPacket Clone(){return new ProtobufPacket();}protected override object OnRead(ISession session, PipeStream stream){Type type = TypeHeaer.ReadType(stream);return ProtoBuf.Meta.RuntimeTypeModel.Default.Deserialize(type, stream, null, null, CurrentSize - 4);}protected override void OnWrite(ISession session, object data, PipeStream stream){TypeHeaer.WriteType(data, stream);ProtoBuf.Meta.RuntimeTypeModel.Default.Serialize(stream, data);}}

分析器定义CustomTypeHeader用于管理消息类型和数据的转换,并在协议分析器静态初始化的时候把当前程序集中所有消息映射关系加载进去。

  • 消息编码

       OnWrite方法负责消息编码,写入消息类型,然后再写入Protobuf序列化后的数据流。

  • 消息解码

       OnRead方法负责消息解码, 先读取消息类型,然后再拿数据流中的数据反序列化到相应的对象。正常做法这里需要判断没有获取到正常的消息类型,没有则抛对应的异常。

        通过以上简单的扩展,一个基于Protobuf的通讯应用协议就扩展完成。

定义消息

       在这个示例中使用了Protobuf.net组件,用这组件在定义消息的时候还是要遵循某些规则的,接下来看一下消息的定义:

    [MessageType(1)][ProtoContract]public class Register{[ProtoMember(1)]public string Name { get; set; }[ProtoMember(2)]public string EMail { get; set; }[ProtoMember(3)]public string Password { get; set; }}[MessageType(2)][ProtoContract]public class RegisterResult{[ProtoMember(1)]public bool Success { get; set; }[ProtoMember(2)]public string Message { get; set; }}

使用Protobuf.net组件需要用ProtoContract来描述一个序列化消息,并用ProtoMember来描述对应的成员属性。MessageType特性用于描述消息类型对应关系。

制定服务

        针对有协议解释对象的TCP服务在处理上和基础的hello world服务差不多,只是重写接管的消息处理方法有所不同。

class Program : ServerHandlerBase
{static IServer mServer;static void Main(string[] args){mServer = SocketFactory.CreateTcpServer(new Program(), new ProtobufPacket());mServer.Options.LogLevel = LogType.Info;       //mServer.Options.DefaultListen.Port=9090//mServer.Options.DefaultListen.SSL = true;//mServer.Options.DefaultListen.CertificateFile = "ssl.pfx";//mServer.Options.DefaultListen.CertificatePassword = "123456";mServer.Open();System.Threading.Thread.Sleep(-1);}protected override void OnReceiveMessage(IServer server, ISession session, object message){RegisterResult result = new RegisterResult();if (message is Register register){server.Log(LogType.Info, session, $"{session.RemoteEndPoint} 注册 {register.Name}");result.Success = true;result.Message = $"{register.Name}你已注册成功,注册邮件地址:{register.EMail}";}else{result.Success = false;result.Message = "非法请求";}session.Send(result);base.OnReceiveMessage(server, session, message);}
}

通过重写OnReceiveMessage方法来接管消息处理,在SSL处理上和之前的hello world示例是一样的配置方式。

客户端访问

        组件提供了AwaiterClient对象来实现基于async/await的消息接收处理,所以在这个示例中就没有使用AsyncTcpClient这个类来处理了(AsyncTcpClient是基于事件方式接收消息在处理上相对麻烦一些)。

class Program
{static async Task Main(string[] args){var client = new AwaiterClient("localhost", 9090, new ProtobufClientPacket());while (true){Register register = new Register();Console.Write("Enter you name:");register.Name = Console.ReadLine();Console.Write("Enter you email:");register.EMail = Console.ReadLine();Console.Write("Enter you password:");register.Password = Console.ReadLine();var result = await client.ReceiveFrom<RegisterResult>(register);Console.WriteLine($"{result.Success} {result.Message}");Console.WriteLine("-".PadLeft(100, '-'));}}
}

以上代码是向服务端发送一个注册信息并等待返回输出;通过AwaiterClient的ReciveFrom<T>方法可以在发送消息后等待一个消息返回;以下示例是运行显示效果。

小结

       虽然传递消息比起直接数据流操作方便很多,但如果针对每个逻辑都写请求和响应其工作也是相当繁琐的。组件有专门针对接口远程调用扩展组件

https://github.com/IKende/XRPC

下载

链接:https://pan.baidu.com/s/118Qal6kJKZ6T9tglaZT3bw

提取码:1b84

【BeetleX通讯框架代码详解】
BeetleX

开源跨平台通讯框架(支持TLS)
轻松实现高性能:tcp、http、websocket、redis、rpc和网关等服务应用

https://beetlex.io

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

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

相关文章

leetcode18. 四数之和

一:题目 二:上码 class Solution { public:/**思路:1.这个跟三数之和差别在于本题加了一层循环,就是我们将第二层循环加在了我们遍历的第一个元素的后面2.其他跟三数之和解题思路一样*/vector<vector<int>> fourSum(vector<int>& nums, int target) {vec…

面试 .NET 开发​,为什么也要考算法?​

最近有不少人面试&#xff0c;我发现很多候选人&#xff0c;聊起架构、框架侃侃而谈&#xff0c;但一写代码&#xff0c;就暴露真实水平。说白了&#xff0c;还是基本功不够扎实。在我看来&#xff0c;所有基本功中&#xff0c;最核心的一定是数据结构与算法。也因此&#xff0…

leetcode344. 反转字符串

一:题目 二:上码 class Solution { public:/**思路:利用双指针来进行处理*/void reverseString(vector<char>& s) {for (int i 0,j s.size()-1; i < j; i,j--) {swap(s[i],s[j]);}} };

跟我一起学.NetCore之WebApi接口裸奔有风险(Jwt)

前言撸码需谨慎&#xff0c;裸奔有风险。经常在一些技术交流群中了解到&#xff0c;还有很多小伙伴的项目中Api接口没有做任何安全机制验证&#xff0c;直接就裸奔了&#xff0c;对于一些临时项目或是个人小项目还好&#xff0c;其余的话&#xff0c;建议小伙伴们酌情考虑都加上…

leetcode541. 反转字符串 II

一:题目 二:上码 class Solution { public:/**思路:1.这个我们需要利用到一个库函数 reverse(nums.begin(),nums.end()); // 将字符串反转那么将局部字符串的反转reverse(nums.begin(),nums.begin()2);//表示的是下标左闭右开的 [0,2)2.还有就是在处理每隔2*k这个问题上 我们选…

你是个失败者,有什么资格说话?

这是头哥侃码的第219篇原创这次十一长假&#xff0c;想必有不少朋友和我一样&#xff0c;跟家人聚在一起&#xff0c;吃个饭&#xff0c;喝点小酒&#xff0c;或者吃吃甜点&#xff0c;喝喝下午茶&#xff0c;“享受” 着在疫情严峻形式下难得的宁静时光。两天前&#xff0c;为…

leetcode151. 颠倒字符串中的单词(思路+详解)

一:题目 二:上码 class Solution { public:/**思路:1.去空格(字符串首部的空格 字符串中间的空格 字符串尾部的空格)1>:这里的话 我们就用到了双指针去空格 fastindex遇见空格直接跳过当fastindex遇不见空格&#xff0c;就将值赋值给fastindex;2.字符串反转3.将单词反转*/…

Azure 内容审查器之羞羞图审查

上一篇 Azure 内容审查器之文本审查我们已经介绍了如果使用Azure进行文字内容的审核。对于社区内容&#xff0c;上传的图片是否含有羞羞内容也是需要过虑的。但是最为一般开发者自己很难实现这种级别的智能识别。但是借助Azure的内容审查器可以分分钟实现它。创建内容审查器在使…

在springboot项目中 static中的 style.css加载不出来

一:问题展示 二:问题解决 404问题你就记住 绝逼是路径出了问题 我以前的写法 报错 修改之后的&#xff1a;可以正常显示

聊一聊mongodb中的 explain 和 hint

看到explain和hint的时候&#xff0c;第一个想到的就是mysql&#xff0c;确实&#xff0c;这就是在mysql中借鉴过来的&#xff0c;既然是借鉴过来的&#xff0c;我想大家都知道这两个关键字的用处&#xff0c;话不多说&#xff0c;速速观看~~~一&#xff1a;explain演示 1. 构建…

leetcode28. 实现 strStr()

一:题目 二:上码 class Solution { public:/**思路:1.KMP算法,主要处理的是字符串匹配的问题2.这里边需要用到next数组 也就是前缀表;那么我们为什么要用前缀表呢&#xff0c;当我们进行匹配字符的时候发现匹配到不相同的字符的时候,那么我们就需要在匹配字符串中查询前一个字符…

Blazor 火了,不禁让人想起已死的Silverlight !

Blazor 火了&#xff0c;Blazor是.NET on browser在开放标准下的一次全新尝试&#xff0c;也将是C#成为全平台全栈语言的最后一块拼图。技术上基于Xamarin团队正在开发的一套运行在wasm上的CLR实现。目前Blazor最直接的受益者还是那些想要做前端的C#开发者&#xff0c;有熟悉的…

xshell过期怎么办

一&#xff1a;问题展示 二:问题的解决 如果我们是出于学习的目的的话&#xff0c;那么我们就可以下载家庭版学生版的免费版本 下载地址:https://www.xshell.com/zh/free-for-home-school/ 然后就等着人家给你发邮件就行了 发完邮件点击里面的链接

C#刷剑指Offer | 二叉树中和为某一值的路径

【C#刷题】| 作者 / Edison Zhou这是EdisonTalk的第292篇原创内容我们来用之前学到的数据结构知识来刷《剑指Offer》的一些核心题目&#xff08;精选了其中30道题目&#xff09;&#xff0c;希望对你有帮助&#xff01;本文题目为&#xff1a;二叉树中和为某一值的路径。1题目介…

leetcode459. 重复的子字符串(KMP)

一:题目 二:上码 class Solution { public:/**思路:a b c a b c a b c a b cnext[i] 0 0 0 1 2 3 4 5 6 7 8 9i 0 1 2 3 4 5 6 7 8 9 10 11 length:12next[length-1]:next[11] 9length - next[length-1] 3;//求出我们的单个字符串如果length % (length - next[length-1]…

AA.Dapper升级了

AA.Dapper如何使用AA.Dapper基于dapper进一步封装而成的orm框架&#xff0c;提供增删改查、分页、事务、原生sql的功能&#xff0c;以满足日常的业务开发。1&#xff0e;Repository层&#xff1a;DapperRepository类包含大部分数据库操作如图&#xff1a; DapperContext.Curren…

剑指 Offer 05. 替换空格(java双指针)

一:题目 二:上码 class Solution {/**思路:1.双指针法进行解决2.我们先统计出空格的数量,然后再按空格数*2,扩充成字符串&#xff0c;加入到原来的字符串中3.然后我们定义两个指针 一个是原来数组长度的指针 一个是扩充完数组长度下标的指针4.当我们原来数组长度的指针遇见空…

如何使用 dotTrace 来诊断 netcore 应用的性能问题

最近在为 Newbe.Claptrap 做性能升级&#xff0c;因此将过程中使用到的 dotTrace 软件的基础用法介绍给各位开发者。Newbe.Claptrap 是一个用于轻松应对并发问题的分布式开发框架。如果您是首次阅读本系列文章。建议可以先从本文末尾的入门文章开始了解。开篇摘要dotTrace 是 J…

leetcode232. 用栈实现队列

一:题目 二:上码 class MyQueue { public:/**思路:1.设置两个栈,一个In,一个out,2.模拟入队的话 其实就是 往栈中添加元素3.模拟出队的话&#xff0c;那么是先进先出的 ,我们需要将in中的元素 导入到 out 中&#xff0c;然后出队的话其实也就是 out栈中的栈顶元素。*/stack<…

用.NetCore 编译国产老牌PHP论坛DiscuzX ,世界上最好的语言从此属于.Net 的一员

DiscuzX是北京康盛新创科技有限责任公司推出的一套通用的社区论坛软件系统。自2001年6月面世以来&#xff0c;Discuz!已拥有15年以上的应用历史和200多万网站用户案例&#xff0c;是全球成熟度最高、覆盖率最大的论坛软件系统之一。目前最新版本Discuz! X3.4正式版于2017年8月2…