分享套接字数据包序列化与反序列化方法

分享套接字数据包序列化与反序列化方法

简单说一下,本文不涉及Socket的连接、数据接收,只是对数据包(byte[])的序列化和反序列化方法的封装介绍。

本文目录

  1. 本文背景

  2. 一般操作

  3. 本文操作

  4. 总结

1.本文背景

经常做C/S,客户端与服务端通信基本是TCP/UDP通信,套接字用得飞起。

比如我们有一个系统,这个系统又分几个系统子模块进程:

  1. C++服务端

  2. Android 客户端

  3. iOS 客户端

  4. WPF桌面管理端 ......

几个模块之间通过TCP或者UDP通信,数据包解析与组装是常规操作,我们定义数据包格式如下:

一个数据包包含包头和包体,定义如下:

包头

序号字段名数据类型备注
1消息标识int用于标识数据包是否合法
2名称string当前消息名称,用于标识数据包类型
3版本号int当前消息版本号,允许程序中消息存在多个版本,用于版本迭代

包含这三个字段:消息标识、名称、版本号,唯一确定消息对象。

包体

序号字段名数据类型备注
1字段1数据类型字段1
2字段2数据类型字段2

包体直接定义字段信息,就像定义类属性一样。

另包头与包体中数据类型定义如下:

数据包字段类型定义

序号数据类型备注
1int4个字节的整型值
2string组成格式:字符串实际值字节长度(2个字节)+字符串实际值byte
3char单字节值
4列表组成格式:4个字节列表长度+列表实际数据值byte
5字典同上,具体看源码

其他数据类型类似,复杂数据类型使用4个字节的值字节长度+实际值byte。

给一个测试数据包

序号字段名数据类型备注
1消息标识int取值:0x4A534604
2消息名称string三国信息,取值:"ThreeCountries"
3版本号int取值:1
4编号int给三国一个编号吧,取值:1
5国名string取值:"蜀国"
6皇帝string取值:"刘备"
7大将个数int5
8大将1编号int取值:1
9大将1名字string取值:"张飞"
10大将1备注string取值:"三板斧"
11大将2编号int取值:2
12大将2名字string取值:"关羽"
13大将2备注string取值:"青龙偃月刀"
14大将3编号int取值:3
15大将3名字string取值:"赵云"
16大将3备注string取值:"很猛的"
17大将4编号int取值:4
18大将4名字string取值:"马超"
19大将4备注string取值:"强"
20大将5编号int取值:5
21大将5名字string取值:"黄忠"
22大将5备注string取值:"老当益壮"

大致理解下:

  • 前三个字段是包体:用于标识整个数据包,便于包体解析;

  • 后面的包体,简单说就是三国中的国家信息简介,前三个字段为三国中的一个国家基本信息:编号、国名、皇帝,后面是该国家大将信息列表,每个大将有编号、名称、备注等。

定义数据对象

根据数据包定义,我们可以很快定义类进行使用,不管你是C++还是Java。下面是我用C#写的对应类,用于序列化与反序列化使用:

/// <summary>
/// 三国
/// </summary>
public class ThreeCountries
{/// <summary>/// 获取或者设置 ID/// </summary>public int ID { get; set; }/// <summary>/// 获取或者设置 国名/// </summary>public string Name { get; set; }/// <summary>/// 获取或者设置 皇帝/// </summary>public string Emperor { get; set; }/// <summary>/// 获取或者设置 所选课程列表/// </summary>public List<FamousGeneral> Courses { get; set; }public override string ToString(){return $"三国之一{ID}:{Name}皇帝{Emperor},有 {Courses.Count}名大将";}
}/// <summary>
/// 三国名将
/// </summary>
public class FamousGeneral
{/// <summary>/// 获取或者设置 编号/// </summary>public int ID { get; set; }/// <summary>/// 获取或者设置 名字/// </summary>public string Name { get; set; }/// <summary>/// 获取或者设置 描述/// </summary>public string Memo { get; set; }public override string ToString(){return $"{ID}:{Name}=>{Memo}";}
}

对于上面给的数据包你怎么序列化及反序列化?转换成数据如下,下节接着讨论

ThreeCountries shuKingdom = new ThreeCountries
{ID = 1,Name = "蜀国",Emperor = "刘备",Courses = new System.Collections.Generic.List<FamousGeneral>{new FamousGeneral{ ID=1,Name="张飞",Memo="三板斧"},new FamousGeneral{ ID=2,Name="关羽",Memo="青龙偃月刀"},new FamousGeneral{ ID=3,Name="赵云",Memo="很猛的"},new FamousGeneral{ ID=3,Name="马超",Memo="强"},new FamousGeneral{ ID=3,Name="黄忠",Memo="老当益壮"},}
};

2. 常规操作

序列化

代码太繁琐,我就写个不正规的伪代码吧

定义一个byte数组;
一、写包头
1、写入4字节的消息标识:0x4A534604
计算消息对象名称字符串“ThreeCountries”长度,及转换字符串为byte数组
2、写入2字节的bytes数组长度,写入实际的byte数组值
3、写入4字节的消息版本号
二、写包体
4、写入4字节的大将个数
循环每个大将信息,依次写入
5、写入大将1编号
6、写入大将1名称
7、写入大奖1备注
8、写入大将2编号
9、写入大将3名称
10、写入大奖4备注
...写吐了,省略号

反序列化

不想写了,累

常规操作

定义一个序列化接口,每个网络对象实现其中的序列化与反序列化接口

public interface ISerializeInterface
{byte[] Serialize<T>(T t);T Deserialize<T>(byte[] arr);
}public class ThreeCountries : ISerializeInterface
{public byte[] Serialize<T>(T t){// 将上面的序列化代码写在这}T Deserialize<T>(byte[] arr){// 将上面的反序列化代码写在这,不好意思我没写}
}

3. 本文操作

写了半天的Demo,文章可能就写的有点水了,我估计读者也不会仔细看代码,直接去Github check项目去了,哈哈。

我还是简单说说吧,实现很简单,定义一些特性,下面红框里的代码文件:

序列化特性及帮助类

使用很简单,在上面的数据类上加上特性,改动不多,看下面代码:

/// <summary>
/// 三国
/// </summary>
[NetObject(Name = "ThreeCountries", Version = 1)]
public class ThreeCountries
{/// <summary>/// 获取或者设置 ID/// </summary>[NetObjectProperty(ID = 1)]public int ID { get; set; }/// <summary>/// 获取或者设置 国名/// </summary>[NetObjectProperty(ID = 2)]public string Name { get; set; }/// <summary>/// 获取或者设置 皇帝/// </summary>[NetObjectProperty(ID = 3)]public string Emperor { get; set; }/// <summary>/// 获取或者设置 所选课程列表/// </summary>[NetObjectProperty(ID = 4)]public List<FamousGeneral> Courses { get; set; }public static NetObjectAttribute CurrentObject = null;static ThreeCountries(){CurrentObject = NetObjectSerializeHelper.GetAttribute<ThreeCountries, NetObjectAttribute>(default(ThreeCountries));}public override string ToString(){return $"三国之一{ID}:{Name}皇帝{Emperor},有 {Courses.Count}名大将";}
}/// <summary>
/// 三国名将
/// </summary>
public class FamousGeneral
{/// <summary>/// 获取或者设置 编号/// </summary>[NetObjectProperty(ID = 1)]public int ID { get; set; }/// <summary>/// 获取或者设置 名字/// </summary>[NetObjectProperty(ID = 2)]public string Name { get; set; }/// <summary>/// 获取或者设置 描述/// </summary>[NetObjectProperty(ID = 3)]public string Memo { get; set; }public override string ToString(){return $"{ID}:{Name}=>{Memo}";}
}

仔细看的话,只在外层类(ThreeCountries)上加了NetObject特性,和属性上加了NetObjectProperty特性,分别标识消息名称、版本号及每个属性的序列化与反序列化顺序即可,类中使用的子对象Courses属性,也只需要加属性特性即可,如上。

下面添加单元测试,并且测试通过:

单元测试通过

4. 总结

用这套代码(demo,有所改变,但也差不多),完成了几个类似的项目,每次数据通信联调、测试问题,C++和java的同事找我时,我就说:

"你先看你自己数据包的序列化和反序列化代码有没有问题,我这不会出问题的,完全按数据包格式转的。"

刚开始还在那闹,后面定位几次问题后,类似的问题他们就没再找我了,偷笑中。

demo写了半天,还是有点累,源码:见开源项目TerminalMACS。

原文链接:https://dotnet9.com/16583.html

欢迎关注我的微信公众号:Dotnet9

Dotnet9微信公众号

谢谢您的支持,需要任何资源,只需要在公众号后台回复对应数字即可,切记只回复“数字”:

01:dotnet
02:java
03:android
04:C++
05:qt
06:react

没有的资源或资源链接失效,请给我留言或加我微信,通过百度网盘好友分享。
另:大部分资源可在我的网站搜索哦:https://dotnet9.com

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

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

相关文章

leetcode22. 括号生成(回溯)

一:题目 二:上码 class Solution {public List<String> generateParenthesis(int n) {List<String> ans new ArrayList<>();def(ans,new StringBuilder(),n,n);return ans;}/**left:左边还可以用的括号数量right:右边还可以用的括号数量*/public void def(…

leetcode31. 下一个排列

一:题目 二:上码 class Solution {/**规律: 从后往前找到那个比其小的数进行交换 然后 在小的数后面的数都进行排序12345 --> 1235412354 --> 12453 --> 12435*/public void nextPermutation(int[] nums) {int len nums.length;for (int i len - 1; i > 0; i--)…

回顾 | 进击吧! Blazor !第三期 信息交互

Blazor 是一个 Web UI 框架&#xff0c;可通过 WebAssembly 在任意浏览器中运行 .Net 。Blazor 旨在简化快速的单页面 .Net 浏览器应用的构建过程&#xff0c;它虽然使用了诸如 CSS 和 HTML 之类的 Web 技术&#xff0c;但它使用 C&#xff03;语言和 Razor 语法代替 JavaScrip…

回顾 | 进击吧! Blazor !第四期 组件开发

Blazor 是一个 Web UI 框架&#xff0c;可通过 WebAssembly 在任意浏览器中运行 .Net 。Blazor 旨在简化快速的单页面 .Net 浏览器应用的构建过程&#xff0c;它虽然使用了诸如 CSS 和 HTML 之类的 Web 技术&#xff0c;但它使用 C&#xff03;语言和 Razor 语法代替 JavaScrip…

面试官:请问一条select的语句的执行会发生什么?

文章目录前言:一:执行一条select的概览二:具体流程1:连接器(1):步骤(2):浅浅来一下细节2:查询缓存(1):mysql5.8之前的幸福时光(2):mysql5.8之后的悲惨结果3:解析器(解析sql)(1):词法解析(2):语法解析4.执行sql(1):预处理阶段(2):优化阶段(3):执行器(1):概述(2):三种方式a:主键索…

跟我一起学.NetCore之MVC过滤器,这篇看完走路可以仰着头走

前言MVC过滤器在之前Asp.Net的时候就已经广泛使用啦&#xff0c;不管是面试还是工作&#xff0c;总有一个考点或是需求涉及到&#xff0c;可以毫不疑问的说&#xff0c;这个技术点是非常重要的&#xff1b; 在之前参与的面试中&#xff0c;得知很多小伙伴只知道有一两个过滤器&…

彭博社:中企游说政府否决英伟达收购Arm

9月14日&#xff0c;英伟达与软银宣布达成最终协议&#xff0c;英伟达将以400亿美元的价格从软银收购ARM。在台积电明确于9月15日后不再向HW的ARM提供代工服务之后&#xff0c;一家美国公司又将ARM收入囊中&#xff0c;这使国产ARM CPU在设计和制造环节都存在巨大风险&#xff…

Explain各个字段的含义

文章目录[TOC]1:expanin的结果示例2:各个字段的含义(1):id(2):select_type(3):table(4):type&#xff08;重要 我们利用索引查找出来的记录显示&#xff09;(5): possible_keys(6):key(7):key_len(8):ref(8):rows(重要)(9):extra1:expanin的结果示例 mysql> explain select…

asp.net core监控—引入Prometheus(三)

上一篇博文中说到Prometheus有四种指标类型&#xff1a;Counter&#xff08;计数器&#xff09;、Gauge&#xff08;仪表盘&#xff09;、Histogram&#xff08;直方图&#xff09;、Summary&#xff08;摘要&#xff09;&#xff0c;并且我们做了一个Counter的Demo&#xff0c…

秋招日常(一天三封感谢信)

就离谱 上午收到两封 搞得复习贼没心态 下午打完球回来一看手机又收到一封 这个有点伤 自己测评完 笔试 笔试完 约面 技术面过了 hr又面 面完说等消息 我寻思hr面能有啥可挂的 就离谱 一想到自己经过那么多轮 还是挂了 就难受 什么鬼 求求了 给个offer吧 要不我快成了天天向下的…

asp.net core监控—引入Prometheus(一)

Prometheus是CNCF毕业的第二个项目&#xff0c;算是明星产品&#xff08;可自行了解Prometheus的功能&#xff09;&#xff0c;asp.net core当然不能错过与之配套使用。在.net中是通过prometheus.net【https://github.com/prometheus-net/prometheus-net】引入的。上图是用Prom…

1024福利 | .NET社区联合清华大学出版社送好书来啦!

话不多说&#xff0c;直入主题。.NET社区各大公众号联合清华大学出版社为粉丝送上1024的福利&#xff0c;还请诸位笑纳&#xff01;&#xff01;&#xff01;有哪些书呢&#xff1f;.NET并发编程实战 作者&#xff1a;[美] 里卡尔多特雷尔&#xff08;Riccardo Terrell&#xf…

asp.net core监控—引入Prometheus(二)

上一篇博文中&#xff0c;说明了怎么引进Prometheus到asp.net core项目中&#xff0c;因为是Demo&#xff0c;所以Prometheus和Grafana都是windows版本&#xff0c;本地执行的&#xff0c;生产环境上这些服务可以根据的公司的架构&#xff0c;放到适合的环境内&#xff0c;现在…

ASP.NET Core Blazor Webassembly 之 渐进式应用(PWA)

Blazor支持渐进式应用开发也就是PWA。使用PWA模式可以使得web应用有原生应用般的体验。什么是PWAPWA应用是指那些使用指定技术和标准模式来开发的web应用&#xff0c;这将同时赋予它们web应用和原生应用的特性。例如&#xff0c;web应用更加易于发现——相比于安装应用&#xf…

TCP三次握手(详解)

一&#xff1a;引出 客户端与服务器之间数据的发送和返回的过程当中需要创建一个叫TCP connection的东西&#xff1b;由于TCP不存在连接的概念&#xff0c;只存在请求和响应&#xff0c;请求和响应都是数据包&#xff0c;它们之间都是经过由TCP创建的一个从客户端发起&#xf…

进击吧! Blazor !第五期 安全

Blazor 是一个 Web UI 框架&#xff0c;可通过 WebAssembly 在任意浏览器中运行 .Net 。Blazor 旨在简化快速的单页面 .Net 浏览器应用的构建过程&#xff0c;它虽然使用了诸如 CSS 和 HTML 之类的 Web 技术&#xff0c;但它使用 C&#xff03;语言和 Razor 语法代替 JavaScrip…

有一种无耻叫 “我是为你着想”

这是头哥侃码的第221篇原创十一之后&#xff0c;我的状态一直不好&#xff0c;总感觉胸口有东西堵着&#xff0c;时不时还会觉得呼吸困难。上周末&#xff0c;我咨询了几位有医学背景的朋友&#xff0c;有说是因为季节转换而造成的身体不适&#xff0c;不用在意&#xff0c;但也…

asp.net core监控—引入Prometheus(四)

上一篇博文中说到Prometheus有四种指标类型&#xff1a;Counter&#xff08;计数器&#xff09;、Gauge&#xff08;仪表盘&#xff09;、Histogram&#xff08;直方图&#xff09;、Summary&#xff08;摘要&#xff09;&#xff0c;并且我们做了一个Counter的Demo&#xff0c…

[开源] .Net ORM FreeSql 1.10.0 稳步向前

写在开头FreeSql 是 .NET 开源生态下的 ORM 轮子&#xff0c;转眼快两年了&#xff0c;说真的开源不容易&#xff08;只有经历过才明白&#xff09;。今天带点干货和湿货给大家&#xff0c;先说下湿货。认识我的人&#xff0c;知道 CSRedisCore 是我写的另外一个开源组件&#…