已解决
对于构建自定义协议的思考(Java)
来自网友在路上 149849提问 提问时间:2023-10-26 15:22:05阅读次数: 49
最佳答案 问答题库498位专家为你答疑解惑
工作转眼也1年时间了,回顾历程,协议占了绝大多数
JSON(比较常见的通信文本了),protoBuf(小编有写过教程),自定义协议(字节拼接,在一些iot领域中的标准几乎都是字节拼接),当然还有很多其他的但是我不会,还有通过asn完成协议(没接触过)
对于JSON和protoBuf来说,相对简单,因为有现成的库调用JSON,protoBuf编译器;
而对于字节拼接的话可能比较复杂,或者说本来不复杂,但是协议复杂,拼接就复杂了;
而拼接字节形式的协议,又涉及到大端小端模式(大端模式是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端;而小端模式是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端)
简单说明就是:大端是将一个数直接转成bytes数组;而小端则需要对数组进行reverse反转操作后的数组;
假设有这样的一个协议:(下面以大端为例子)
协议头:
协议内容:
感知物体对象:
那么我在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;@Overridepublic 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;@Overridepublic 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;@Overridepublic 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;@Datapublic 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));}}
感觉这样能减少在代码内部的侵入计算,编写自定义协议也更加方便;
文章有不足的地方还望指正,小子修改
当然大佬们有什么更好的方法,可以沟通交流一下
查看全文
99%的人还看了
相似问题
- JVM:字节码文件,类的生命周期,类加载器
- 网工内推 | 字节原厂,正式编,网络工程师,最高30K*15薪
- Go 以小端字节序修改文件
- UDP端口接收到的字节流如何转为QJsonObject、QJsonArray的方法
- 《2020年最新面经》—字节跳动Java社招面试题
- 计算Qt中的QAudioOutput缓冲区未播放的音频字节数对应时长
- 字节面试:请说一下DDD的流程,用电商系统为场景
- 深入理解JVM虚拟机第二十一篇:详解JVM当中的操作数在栈以及分析操作数栈与字节码指令和执行引擎的关系图解
- 【Linux网络编程_TCP/UDP_字节序_套接字 实现: FTP 项目_局域网聊天项目 (已开源) 】.md updata:23/11/05
- 【项目源码】反编译Java字节码生成源码
猜你感兴趣
版权申明
本文"对于构建自定义协议的思考(Java)":http://eshow365.cn/6-25174-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!
- 上一篇: Lua 事件触发机制(注册,触发)
- 下一篇: 随机生成验证码实例