自定义通信协议设计基础

2024-08-24 01:32

本文主要是介绍自定义通信协议设计基础,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文转自:http://www.360doc.com/content/14/0915/11/1073512_409611008.shtml

  对于很多设备之间的通信,经常需要自己设计一套通信协议。当然此处的通信协议一般都是建立在TCPIP协议等协议基础之上的协议,也就是在已有协议的基础之上,在定义一套协议。例如:有一套检测降雨量的设备(一般为简单的嵌入式设备)需要把采集到的的数据上报给中心服务器(一般为一台性能特别好的计算机)。就需要一套通信协议。以保证,嵌入式设备上发的数据,可以被中心服务器正确的理解和处理。再例如:在桥梁检测的项目中,会检测很多桥梁的数据,应力,索力,温度等,这些检测设备一般都是由简单的传感器组成的嵌入式设备 ,需要通过各种方式把采集到的的数据上报给中心服务器,中心服务器经过分析处理后,再进一步判断桥梁的各种状态。这些都涉及到自定义通信协议。

但这些自定义通信协议如何设计?有设计到那些方面?

协议的设计,是为了保证双方能够正常的通信,由于上位设备和下位设备一般是不同的设备,处理能力有很大差异,这些都是设计协议必须考虑的问题。

  一套完整的协议,通常包含很多命令,每一个命令都会规定一个完整的命令(也就是一个完整的数据帧)包含哪些部分,一般包含以下几部分:

1、数据帧的组成的形式

一般形式有字节流(有的地方也叫做二进制协议)和字符流。字节流一般会规定每一个字节表示的含义,而字符流由于都是可见的字符,一般会规定,字符的含义。

2、数据帧头和尾

数据帧头和尾其实是为了解析数据而设计的,主要是为了获取一个完整的帧。由于网络的不确定性,无法保证一条完整的数据帧的一次性就发送给对方。一般选择用很少出现的字节或者字符作为数据帧头和尾。

例如我曾经解析过得MODE 04 PROTOCOL的一套协议,就是以0x03,0x14开头的,由于MODE 04 PROTOCOL是字节流协议,因此规定了命令的开头两个字节是0x03,0x14,还曾经解析过字符流的协议,命令是以##开头数据帧尾有时会有,有时没有,例如MODE 04 PROTOCOL就没有协议尾,因为它有两个字节表示本条数据帧的长度,所以没必要规定数据帧尾。相反,如果无法判断一条命令的长度,就会规定数据帧如何结束。如果数据帧长度都是一样的,也没有必要规定,但实际中很少遇到数据帧长度是固定的情况。

3、数据帧的验证部分

对于字节流的协议,一般会规定验证数据帧的验证部分,例如MODE 04 PROTOCOL就规定了数据帧最后两个字节是crc验证部分。

对于字符流的也可以加验证字段,但因为每一部分都都是可视的字符,也可以不加。

4、转义字符

再少出现的字符由于数据帧内容的不确定性,也有可能在数据帧内部出现,例如:MODE 04 PROTOCOL协议当数据帧内部出现了0x03,0x14,也就是数据帧规定的开始部分,就必须转义,否则就会解析出错。导致一个数据帧变成两部分不完整无法理解的数据帧。

5、命令字及其他

命令字就是标示此数据帧,需要完成的命令,例如:读取时间命令数据帧,就有一部分标示此数据帧是读取时间,设置时间命令数据帧就有一部分标示此数据帧是用来设置时间的,当然会有命令内容例如把时间调整到多少。


6、心跳包

心跳包作为一条很特殊的数据帧,作用其实和人的心跳类似。每隔一段时间,就会发送一条很特殊的数据帧心跳包。作用就是表明此设备还在工作。

例如QQ的在上状态应该就是通过类似心跳包的设计来完成的。但在无线领域还有其他作用,避免已经建立的链接断开。尤其数据是通过GPRS发送时,如果长时间不发送数据,网络运营商就会回收链接,下次发送数据时,就必须重新建立链接,这对于需要永远在线的设备或者是需要随时唤醒的设备来说,显然是不行的。

对比:

字节流协议难度显然比字符流大很多,解析过程也更复杂,如果没有协议文档,几乎不能解析,因为收到的就是一串毫无意思的数字,一个字节处理错误就完全可能导致整条数据解析错误,此外字节流还需要规定大端模式和小端模式等。当然好处就是,传输同样的信息,数据量明显少很多。

字符流就简单很多,解析的过程可能就是一个正则表达式。


这篇关于自定义通信协议设计基础的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1101066

相关文章

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

Java实现自定义table宽高的示例代码

《Java实现自定义table宽高的示例代码》在桌面应用、管理系统乃至报表工具中,表格(JTable)作为最常用的数据展示组件,不仅承载对数据的增删改查,还需要配合布局与视觉需求,而JavaSwing... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

一文详解Java Stream的sorted自定义排序

《一文详解JavaStream的sorted自定义排序》Javastream中的sorted方法是用于对流中的元素进行排序的方法,它可以接受一个comparator参数,用于指定排序规则,sorte... 目录一、sorted 操作的基础原理二、自定义排序的实现方式1. Comparator 接口的 Lam

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据

如何自定义一个log适配器starter

《如何自定义一个log适配器starter》:本文主要介绍如何自定义一个log适配器starter的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录需求Starter 项目目录结构pom.XML 配置LogInitializer实现MDCInterceptor

MyBatis设计SQL返回布尔值(Boolean)的常见方法

《MyBatis设计SQL返回布尔值(Boolean)的常见方法》这篇文章主要为大家详细介绍了MyBatis设计SQL返回布尔值(Boolean)的几种常见方法,文中的示例代码讲解详细,感兴趣的小伙伴... 目录方案一:使用COUNT查询存在性(推荐)方案二:条件表达式直接返回布尔方案三:存在性检查(EXI

安装centos8设置基础软件仓库时出错的解决方案

《安装centos8设置基础软件仓库时出错的解决方案》:本文主要介绍安装centos8设置基础软件仓库时出错的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录安装Centos8设置基础软件仓库时出错版本 8版本 8.2.200android4版本 javas

Linux基础命令@grep、wc、管道符的使用详解

《Linux基础命令@grep、wc、管道符的使用详解》:本文主要介绍Linux基础命令@grep、wc、管道符的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录grep概念语法作用演示一演示二演示三,带选项 -nwc概念语法作用wc,不带选项-c,统计字节数-

Druid连接池实现自定义数据库密码加解密功能

《Druid连接池实现自定义数据库密码加解密功能》在现代应用开发中,数据安全是至关重要的,本文将介绍如何在​​Druid​​连接池中实现自定义的数据库密码加解密功能,有需要的小伙伴可以参考一下... 目录1. 环境准备2. 密码加密算法的选择3. 自定义 ​​DruidDataSource​​ 的密码解密3

spring-gateway filters添加自定义过滤器实现流程分析(可插拔)

《spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔)》:本文主要介绍spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔),本文通过实例图... 目录需求背景需求拆解设计流程及作用域逻辑处理代码逻辑需求背景公司要求,通过公司网络代理访问的请求需要做请