Skip to content

Repository files navigation

Protocol for Java

简介

该协议主要用于对象与二进制流的序列化和反序列化(主要功能类似Json格式协议),在物联网快速发展的时代,快速的迭代是发展的根本,但是在不断的迭代的过程中开发人员对产品的理解也在不断的升级,这就造成在协议的制定过程中虽然规则渐渐完善,但是硬件产品发出去后与服务端的接口将在也不能被修改,后端项目越往后走可维护性越差最终导致这个项目成为了一个硬骨头。

该协议主要面向于业务,解决面向底层时架构层次冗杂的代码导致后期难维护,毕竟总是有第一个版本老板说"我今天晚上就要",该协议将减少你90%开发工作量与联调的时间,拿出更多的时间去学学Python吧,但不管学什么你将节约的生命。

下个大版本将开发spring-boot-starter-protocol4java用于更加方便的使用并尽量减少开发量与使用成本。

协议结构

  • Herder(协议头)

协议头中包含命令和版本两个属性,Command表示此次通信代表做什么事情;命令索引全局唯一不能重复,而Version表示这个这次命令的版本号;版本号全局不唯一,在此次命令下唯一,通过命令和版本来决定某个协议。

Lengthdefinitionremark
1Command命令(描述此次通信代表做什么事情)
1Version版本(描述这次命令的版本)
  • PackedList(数据段集合)

数据段集合中包含多个数据段,Total packed表示数据段的数量

Lengthdefinitionremark
1Total packed数据段总包数(描述数据段的数量)
  • Packed(数据段)

一个数据段表示一个字段,Code index字段索引;字段索引全局不唯一,在此次命令下唯一,Type index类型索引;类型索引全局唯一

Lengthdefinitionremark
1Code index字段索引(描述字段对应的索引)
1Type index类型索引(描述字段的类型对应的索引)
  • ElementList(元素集合)

元素集合中包含元素个数Element size此处将数据段的的数据的存储方式抽象成了数组,如果元素个数为1时表示只有一个元素,证明该字段不是一个数组,如果元素个数>1时证明该字段是一个数组

Lengthdefinitionremark
2Element size元素个数(描述字段对应的索引)
  • Element(元素)

Element表示数组中的元素;Element[i] Length表示第i个元素的长度;Element[i]表示元素n的数据(元素的大小长度是由元素n_Element[i] Length指定的)

Lengthdefinitionremark
2Element[i] Length元素i的长度(描述第i个元素的长度)
变长Element[i]元素i的数据(元素的大小长度是由元素i_Element[i] Length指定的)
2Element[n] Length元素n的长度(描述这次命令的版本)
变长Element[n]元素n的数据(元素的大小长度是由元素n_Element[i] Length指定的)

协议支持类型

因为最初的设计是与C语言程序交互所以兼容了C语言中大部分常用类型

CJavaJava TypeConvert implements
signed charbyteSignedChar2byteTypeConvert
signed shortshortSignedShort2shortTypeConvert
signed intintSignedInt2integerTypeConvert
signed long longlongSignedLongLong2longTypeConvert
floatfloatFloatTypeConvert
doubledoubleDoubleTypeConvert
0/1booleanBooleanTypeConvert
char arrayStringStringTypeConvert
unsigned charbyteUnsignedChar2byteTypeConvert
unsigned shortshortUnsignedShort2shortTypeConvert
unsigned intintUnsignedInt2integerTypeConvert
unsigned long longlongUnsignedLongLong2longTypeConvert

该协议支持自定义类型只要实现TypeConvert配合@Typed注解即可,可参考以上TypeConvert的编写方式

协议架构

协议架构图-V2

流程图

流程图

Samples

packageio.github.guoxinl.protocol.samples;
importio.github.guoxinl.protocol.analysis.DataProtocolCallback;
importio.github.guoxinl.protocol.analysis.conf.convert.SignedInt2integerTypeConvert;
importio.github.guoxinl.protocol.analysis.conf.convert.SignedShort2shortTypeConvert;
importio.github.guoxinl.protocol.analysis.conf.convert.StringTypeConvert;
importio.github.guoxinl.protocol.analysis.conf.register.ProtocolEntityRegister;
importio.github.guoxinl.protocol.analysis.model.DataProtocolCallbackService;
importio.github.guoxinl.protocol.analysis.model.anno.Callback;
importio.github.guoxinl.protocol.analysis.model.anno.Protocol;
importio.github.guoxinl.protocol.analysis.model.anno.Type;
importio.github.guoxinl.protocol.analysis.model.common.ResultProtocol;
importio.github.guoxinl.protocol.analysis.model.entity.DataProtocol;
importio.github.guoxinl.protocol.analysis.model.entity.ProtocolEntity;
importio.netty.buffer.ByteBuf;
importio.netty.buffer.ByteBufUtil;
importio.netty.buffer.Unpooled;
importlombok.Getter;
importlombok.Setter;
importlombok.extern.slf4j.Slf4j;
importjava.util.Arrays;
/** * Create by guoxin on 2018/6/14 */publicclassProtocol4javaSamplesApplication {
/** * 协议请求对象 */@Getter@Setter@Protocol(commandIndex = 1, version = 1)
@Callback(callback = ResultDataProtocolCallbackService.class)
publicstaticclassUpgradeProtocolimplementsProtocolEntity {
@Type(convert = StringTypeConvert.class)
privateStringaaa;
@Type(convert = StringTypeConvert.class)
privateStringbbb;
@Type(convert = SignedInt2integerTypeConvert.class)
privateint[] ccc;
@Type(convert = StringTypeConvert.class)
privateString[] ddd;
@Type(convert = SignedShort2shortTypeConvert.class)
privateshort[] eee;
}
/** * 回调业务逻辑类 */@Slf4jpublicstaticclassResultDataProtocolCallbackServiceimplementsDataProtocolCallbackService<UpgradeProtocol, ResultProtocol> {
@OverridepublicResultProtocolcall(UpgradeProtocolprotocolEntity) {
log.info("Aaa: {}", protocolEntity.getAaa());
log.info("Bbb: {}", protocolEntity.getBbb());
log.info("Ccc: {}", Arrays.toString(protocolEntity.getCcc()));
log.info("Ddd: {}", Arrays.toString(protocolEntity.getDdd()));
log.info("Eee: {}", Arrays.toString(protocolEntity.getEee()));
// 默认协议响应对象returnResultProtocol.success();
}
}
publicstaticvoidmain(String[] args) {
// 注册协议对象ProtocolEntityRegisterregister = newProtocolEntityRegister();
register.register(UpgradeProtocol.class);
// 实例化协议对象并赋值UpgradeProtocolupgradeProtocol = newUpgradeProtocol();
upgradeProtocol.setEee(newshort[] {1,2,3,4,5});
upgradeProtocol.setCcc(newint[]{5,4,3,2,1});
upgradeProtocol.setBbb("bbb");
upgradeProtocol.setDdd(newString[] {"ddd","ddd","ddd"});
upgradeProtocol.setAaa("aaa");
// 将协议对象转换为协议适配对象DataProtocoldataProtocol1 = DataProtocol.convert(upgradeProtocol);
// 将协议适配对象转化为字节流ByteBufbuffer = Unpooled.buffer();
dataProtocol1.serialization(buffer);
System.out.println("request:" + ByteBufUtil.hexDump(buffer));
// 模拟业务逻辑DataProtocolCallbackcallback = newDataProtocolCallback();
ByteBufcall = callback.call(buffer);
System.out.println("response:" + ByteBufUtil.hexDump(call));
}
}

多端适配

讲道理,这个协议目前暂时只能做到Java to java之间的传输,寻找C ,Go ,Python... 开发者一起完成这个开源项目

所以在此向各路高手发出请帖,一起共同华山论剑,共同追逐完美的code

后续开发计划

开发计划

About

自描述通用传输协议

Resources

Stars

8 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages