对于构建自定义协议的思考(Java)

工作转眼也1年时间了,回顾历程,协议占了绝大多数
在这里插入图片描述

JSON(比较常见的通信文本了),protoBuf(小编有写过教程),自定义协议(字节拼接,在一些iot领域中的标准几乎都是字节拼接),当然还有很多其他的但是我不会,还有通过asn完成协议(没接触过)
对于JSON和protoBuf来说,相对简单,因为有现成的库调用JSON,protoBuf编译器;
而对于字节拼接的话可能比较复杂,或者说本来不复杂,但是协议复杂,拼接就复杂了;

而拼接字节形式的协议,又涉及到大端小端模式(大端模式是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端;而小端模式是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端)
简单说明就是:大端是将一个数直接转成bytes数组;而小端则需要对数组进行reverse反转操作后的数组;

假设有这样的一个协议:(下面以大端为例子)
协议头:

消息名称占用字节数
消息头1
消息类型1
消息版本1
消息时间戳8
消息体1+15*n

协议内容:

消息名称占用字节数
感知物体数量1
感知物体列表15*n

感知物体对象:

消息名称占用字节数
感知物体id1
感知物速度4
感知物航向角2
感知物经度4
感知物纬度4

那么我在Java中将构建这样几个对象用来实现协议:
结构:
在这里插入图片描述
实体上层接口规范:Protocol

public abstract class Protocol {
    byte[] bytes = new byte[0];//抽象出来的bytes数组,用于存储继承者的最终字节

    void toBytes() {//抽象出来的方法,约束子类必须实现

    }
}

消息头:

@Data
public class ProtocolHead<T extends Protocol> extends Protocol {
    private byte msgHead;
    private byte msgType;
    private byte msgVersion;
    private long timeStamp;
    private T msgBody;

    @Override
    public void toBytes() {
        msgBody.toBytes();//将msgBody 字节数组化
        ByteBuffer buffer = ByteBuffer.allocate(1 + 1 + 1 + 8 + msgBody.bytes.length);
        buffer.put(msgHead);
        buffer.put(msgType);
        buffer.put(msgVersion);
        buffer.putLong(timeStamp);
        buffer.put(msgBody.bytes);
        bytes = buffer.array();
    }
}

消息体:

@Data
public class ProtocolBody extends Protocol {
    private byte perNum;
    private PerceptionData[] perceptionDataArr;

    @Override
    public void toBytes() {
        int size = 1;
        for (byte i = 0; i < perNum; i++) {
            perceptionDataArr[i].toBytes();//将每一个感知对象 字节化
            size += perceptionDataArr[i].bytes.length;
        }
        ByteBuffer buffer = ByteBuffer.allocate(size);
        for (byte i = 0; i < perNum; i++) {
            buffer.put(perceptionDataArr[i].bytes);
        }
        bytes=buffer.array();
    }
}

消息内容:

@Data
public class PerceptionData extends Protocol {

    private byte id;
    private int speed;
    private short heading;
    private int lon;
    private int lat;

    @Override
    public void toBytes() {
        ByteBuffer buffer = ByteBuffer.allocate(1 + 4 + 2 + 4 + 4);
        buffer.put(id);
        buffer.putInt(speed);
        buffer.putShort(heading);
        buffer.putInt(lon);
        buffer.putInt(lat);
        bytes= buffer.array();
    }
}

输入数据(模拟设备传入的数据)

@Data
public class InputPerData {

    private long timeStamp;
    private List<Per> perList;


    @Data
   public static class Per {
        private byte id;
        private int speed;
        private short heading;
        private int lon;
        private int lat;
    }
}

解析类 convert 转换:

public class EncodeParser {

    public byte[] convertData(InputPerData inputPerData) {

        PerceptionData[] perArr = new PerceptionData[inputPerData.getPerList().size()];
        for (int i = 0; i < inputPerData.getPerList().size(); i++) {
            InputPerData.Per inputPer = inputPerData.getPerList().get(i);
            perArr[i] = new PerceptionData();
            perArr[i].setId(inputPer.getId());
            perArr[i].setSpeed(inputPer.getSpeed());
            perArr[i].setHeading(inputPer.getHeading());
            perArr[i].setLon(inputPer.getLon());
            perArr[i].setLat(inputPer.getLat());
        }

        ProtocolBody body = new ProtocolBody();
        body.setPerNum((byte) inputPerData.getPerList().size());
        body.setPerceptionDataArr(perArr);


        ProtocolHead<ProtocolBody> head = new ProtocolHead<>();
        head.setMsgHead((byte) 0x01);
        head.setMsgType((byte) 0x04);
        head.setMsgVersion((byte) 0x01);
        head.setTimeStamp(inputPerData.getTimeStamp());
        head.setMsgBody(body);

        head.toBytes();//调用编码方法

        return head.bytes;


    }

    public static void main(String[] args) {
        InputPerData.Per per = new InputPerData.Per();
        per.setId((byte) 1);
        per.setSpeed(11);
        per.setHeading((short) 180);
        per.setLon(111342345);
        per.setLat(260099888);
        InputPerData.Per per1 = new InputPerData.Per();
        per1.setId((byte) 2);
        per1.setSpeed(10);
        per1.setHeading((short) 120);
        per1.setLon(114909989);
        per1.setLat(269894903);

        EncodeParser parser = new EncodeParser();
        InputPerData input = new InputPerData();
        input.setTimeStamp(System.currentTimeMillis());
        input.setPerList(Lists.newArrayList(per, per1));
        byte[] bytes = parser.convertData(input);//最终byte用于网络通信,常见于 netty的tcp/udp通信
        System.out.println("bytes = " + Arrays.toString(bytes));
    }

}

感觉这样能减少在代码内部的侵入计算,编写自定义协议也更加方便;
文章有不足的地方还望指正,小子修改
当然大佬们有什么更好的方法,可以沟通交流一下

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue+Fullcalendar

vueFullcalendar: vueFullcalendar项目代码https://gitee.com/Oyxgen404/vue--fullcalendar.git

2.2 消元法的概念

一、消元法介绍 消元法&#xff08;elimination&#xff09;是一个求解线性方程组的系统性方法。下面是使用消元法求解一个 2 2 2\times2 22 线性方程组的例子。消元之前&#xff0c;两个方程都有 x x x 和 y y y&#xff0c;消元后&#xff0c;第一个未知数 x x x 将从第…

C#__简单了解XML文档

/* XML(可扩展标记语言)&#xff1a;用于传输和存储数据 XML文档&#xff1a;树结构&#xff1b;包含根元素 XML元素&#xff1a;从开始标签到结束标签的部分 XML语法规则&#xff1a; 1、所有XML元素都必须有结束标签 …

大数据与人工智能的未来已来

大数据与人工智能的定义 大数据&#xff1a; 大数据指的是规模庞大、复杂性高、多样性丰富的数据集合。这些数据通常无法通过传统的数据库管理工具来捕获、存储、管理和处理。大数据的特点包括"3V"&#xff1a; 大量&#xff08;Volume&#xff09;&#xff1a;大数…

html2pdf

页面布局时将需要保存在同一页pdf的dom元素用div包裹&#xff0c;并为该div添加class类名&#xff0c;例如.convertPDF&#xff0c;如果有多页创建多个.convertPDF这个div&#xff0c;再循环保存pdf即可 用到了html2canvas和JsPdf这两个插件&#xff0c;自行站内搜索安装

【Java 进阶篇】Java Request 获取请求参数的通用方式详解

在Java Web开发中&#xff0c;获取HTTP请求的参数是一项基本任务。请求参数可以包含在URL中&#xff0c;也可以包含在请求体中&#xff0c;例如表单提交时的参数。在Java中&#xff0c;可以使用HttpServletRequest对象来获取HTTP请求的参数。本文将详细解释如何使用Java获取HTT…

Response Header中不暴露Server(IIS)版本、ASP.NET及相关版本等信息

ASP MVC开发的Web默认情况下会在请求的回应中暴露Server、X-AspNet-Version、X-AspNetMvc-Version、X-Powered-By等相关服务端信息&#xff0c;公开这些敏感信息会存在一定的安全风险。 X-SourceFiles标头用于被IIS / IIS Express中某些调试模块理解&#xff0c;它包含到磁盘上…

Python 接口自动化 —— requests框架

1.前言 Python内置的urllib模块&#xff0c;也可以用于访问网络资源。但是&#xff0c;它用起来比较麻烦&#xff0c;而且&#xff0c;缺少很多实用的高级功能。因此我们使用 requests 模块进行进行接口测试。 requests官方文档资料地址&#xff1a;http://cn.python-request…

不同网段的IP怎么互通

最近在整理工作的时候发现一个不同网段无法互通的问题&#xff0c;就是我们大家熟知的一级路由和二级路由无法互通的问题。由于需要记录整个过程的完整性&#xff0c;这里也需要详细记录下整个过程&#xff0c;明白的人不用看&#xff0c;可以直接跳过&#xff0c;到解决方法去…

方太描画未来厨房的模样

作者 | 辰纹 来源 | 洞见新研社 不知不觉中&#xff0c;iPhone已经更新到15代了&#xff0c;家里的电视变成了越来越轻薄的液晶屏&#xff0c;过去被称为“老三样”的富康&#xff0c;捷达、桑塔纳&#xff0c;如今也被以特斯拉为代表的新能源智能汽车们所取代…… 类似以上的…

k8s命令式对象管理、命令式对象配置、声明式对象配置管理资源介绍

目录 一.kubernetes资源管理简介 二.三种资源管理方式优缺点比较 三.命令式对象管理介绍 1.kubectl命令语法格式 2.资源类型 &#xff08;1&#xff09;通过“kubectl api-resources”来查看所有的资源 &#xff08;2&#xff09;每列含义 &#xff08;3&#xff09;常…

在线运行C++的网站(欢迎补充)

1、https://cpp.sh/ 谷歌打开&#xff0c;好用 2、https://godbolt.org/ 会显示汇编

IOC课程整理-17 Spring事件

1. Java 事件/监听器编程模型 2. 面向接口的事件/监听器设计模式 3. 面向注解的事件/监听器设计模式 4. Spring 标准事件-ApplicationEvent 5. 基于接口的 Spring 事件监听器 6. 基于注解的 Spring 事件监听器 7. 注册 Spring ApplicationListener 8. Spring 事件发布器 9. Spr…

DoLa:对比层解码提高大型语言模型的事实性

DoLa&#xff1a;对比层解码提高大型语言模型的事实性 摘要1 引言2 方法2.1 事实知识在不同层级上演化2.2 动态早期层选择2.3 预测对比 3 实验3.1 任务3.2 实验设置3.3 多项选择3.3.1 TruthfulQA&#xff1a;多项选择3.3.2 FACTOR&#xff1a;维基、新闻 3.4 开放式文本生成3.4…

《C和指针》(6)指针

问题 如果一个值的类型无法简单地通过观察它的位模式来判断&#xff0c;那么机器是如何知道应该怎样对这个值进行操纵的&#xff1f; 答&#xff1a;机器无法作出判断。编译器根据值的声明类型创建适当的指令&#xff0c;机器只是盲目地执行这些 指令而已。 C为什么没有一种方…

【图像分类】卷积神经网络之ResNet网络模型实现钢轨缺陷识别(附代码和数据集,PyTorch框架)

写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 本篇博文,我们将使用PyTorch深度学习框架搭建ResNet实现钢轨缺陷识别,附完整的项目代码和数据集,可以说是全网…

2023高频前端面试题-浏览器

1. 浏览器是如何解析 CSS 选择器的&#xff1f; 在生成渲染树的过程中&#xff0c;渲染引擎会根据选择器提供的信息来遍历 DOM 树&#xff0c;找到对应的 DOM 节点后将样式规则附加到上面。 来看一段样式选择器代码、以及一段要应用样式的 HTML&#xff1a; .mod-nav h3 spa…

密码学基础

密码学总览 信息安全面临的危险与应对这些威胁的密码技术&#xff1a; 关于上图中的威胁&#xff0c;这里在简单的说明&#xff1a; 窃听&#xff1a;指的是需要保密的消息被第三方获取。篡改&#xff1a;指的是消息的内容被第三方修改&#xff0c;达到欺骗的效果。伪装&…

21.9 Python 使用Selenium库

Selenium是一个自动化测试框架&#xff0c;主要用于Web应用程序的自动化测试。它可以模拟用户在浏览器中的操作&#xff0c;如打开网页、点击链接、填写表单等&#xff0c;并且可以在代码中实现条件判断、异常处理等功能。Selenium最初是用于测试Web应用程序的&#xff0c;但也…

Haproxy负载均衡集群

一、haproxy概念&#xff1a; Haproxy&#xff1a;他也是常用的负载均衡转发 nginx支持四层转发&#xff0c;七层转发 haproxy也可以四层和七层转发 LVS的DR和NAT是基于四层转发 TUN是四层七层 基于四层的转发&#xff1a; LVSnginxhaproxy 基于七层的转发&#xff1a; …
最新文章