这是我参与更文挑战的第18天,活动详情查看: 更文挑战
引言
不好意思各位,最近公司项目比较忙,鸽了好久的文章,现在重新拾起来。
我个人比较愿意将工作过程中学习的知识,问题的解决思路,通用的处理方式等做一个总结,方便自己,也照亮他人。为什么是工作过程中的,因为只有真实的场景下碰到的问题才是有价值的内容,我愿意分享,但是我也做不到像某些大佬一样熬夜肝文章,本着身体是第一位的原则,适当做一些总结是我现在做事的思路。
项目叙述
这次要讲的不是什么复杂的项目,是一个基于WebSocket的通信服务程序。
在做这个项目前,我其实没有接触过通信服务程序这一块内容,之前主要都是写的WebApi和后台管理系统接口。当然我也知道Tcp是面向连接的可靠的,Udp是不可靠的这些基于知识,但在实际的应用场景下使用这还是第一次,可能有些人觉得这种简单的东西有什么好讲的,那这样你可以选择关闭网页,合适的东西应该给合适的人看,这是我的观点。
开发语言c#,开发一个基于WebSocket的通信程序,客户端按照规定的报文格式发送,服务端可以正常解析。
报文格式如下
名称 | 帧头 | 数据长度 | CRC 校验 | 数据段 |
---|---|---|---|---|
长度(字节) | 2 | 2 | 2 | N |
说明 | TT |
所有数据帧, 皆为高字节在前模式, 即小端模式。
CRC 的校验范围为: 从包头至包尾巴。 校验初始, CRC 校验位置要先清零。
CRC 校验方式:
初始校验值为 0xAA, 所有字节依次累加, 最后求和
项目技术预演
没有先例如何开发一个稳定的Tcp通信服务?
在开发本任务前我并没有做通信服务的经验,为了最快成本的减少踩坑和开发顺畅,我选择了使用现成的框架。在综合后我选择了RRMQSocket。
日月之行,若出其中;星汉灿烂,若出其里。
RRQMSocket是一个整合性的、超轻量级的网络通信服务框架。它具有 高并发连接 、 高并发处理 、 事件订阅 、 插件式扩展 、 多线程处理 、 内存池 、 对象池 等特点,让使用者能够更加简单的、快速的搭建网络框架。
选择他的理由其实比较简单,开源【gitee 推荐项目】、有文档、持续维护。
我通过作者提供的文档首先对通信服务有了一个基本了解,然后使用框架编写一个最基本案例:一个简单的tcp通信服务,增加自己对框架的了解。
到此,对框架的工作暂时高一段落。
什么是小端模式
在计算机中一般讲字节序分为两类:Big-Endian
(大端字节序) 和 Little-Endian
(小端字节序)
a) Little-Endian 高位字节在前,低位字节在后。
b) Big-Endian 低位字节在前,高位字节在后。
网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序。
举个小例子:
整数127(十进制)在计算机(64位)中大/小端字节序
c#中对字节序的处理
首先默认的 C# 使用的是小端序。直接上案例,大家可以按照上图进行分析。
1 | ini复制代码using System; |
如何进行大端序和小端序的转换?
在上面的案例中细心的服友肯定已经发现了处理方式
推荐方式
1 | arduino复制代码System.Net.IPAddress.HostToNetworkOrder(本机到网络转换) |
其他方式
字节数组reverse
反转,即得到相反的字节序
1 | scss复制代码byte[].Reverse().ToArray(); |
代码示例
short表示短整形,short 6 占2个字节,内存表现为 06 00 值=06
使用HostToNetworkOrder
将x转换为大端字节表现形式,b=1536 ,内存表现形式00 06
最调用`BitConverter.GetBytes’将大端字节数1536转为大端字节数组表现形式 00 06
1 | ini复制代码short x = 6; |
对于字符串型:使用 System.Text.Encoding.Default.GetBytes();
直接取字串对应字节数组。
CRC校验是什么,有什么作用
crc定义
CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似的算法,以保证数据传输的正确性和完整性。
crc校验作用
在信息的传输过程中,有时会发生误码。
例如,传送1001,接收到1000,这就产生了误码,但接收方并不知道产生了误码。
而当发送方与接收方使用同一标准的CRC校验,就能够判断在信息传输的过程中是否发生了误码。
进制处理相关
c# 在进行进制处理时有一些常用的方法,记录下来方便自己后期回顾
单个10进制转为16进制字符串
1 | vbscript复制代码X.ToString("X2")即转化为大写的16进制。 |
借着这个机会我又重温了一下 string.Format
函数
1 | arduino复制代码Console.WriteLine(string.Format("{0:X}", 12)); //输出A |
字节数组转为字符串,其实就是一个循环
1 | ini复制代码public static string BytesTostring(byte[] bytes) |
官方库自带的字节处理帮助类
using namespace System
BitConverter.方法
参考
本文转载自: 掘金