Netty实战之使用Netty解析交通部JT808协议

1.写此文的目的

使用Netty也有一段时间了,对Netty也有个大概的了解。回想起刚刚使用Netty的时候踩了很多坑,很多Netty的组件也不会使用,或者说用得不够好,不能称之为"最佳实践"。此文的目的便是带领大家使用Netty构建出一个完整的项目,将自己在实际开发经验中整理出的一些最佳实践分享出来,当然这些最佳实践不一定就是真正的最佳实践,只是自己在开发中整理的,或者参考其他优秀的代码一起整理出的,大家如果有什么不同意见或者更好的实践,欢迎大家在评论区分享,大家一起学习一起进步!

2. 项目准备

开发环境:IDEA+JDK1.8+Maven

使用框架: Netty + Spring Boot + Spring Data JPA

其他工具: lombok(没用过的同学建议了解一下,很方便)

3. 开发过程

3.1.认识JT808协议
3.2.构建编/解码器
3.3.构建业务Handler
3.4.Channel的高效管理方式
3.5.一些改进

3.1 认识JT808协议

下面简单介绍一下JT808协议的格式说明,完全版在JT808协议技术规范.pdf

其中消息体属性中我们先只关注消息体长度,不关注其他,分包情况先不考虑。

根据消息头和消息体我们可以抽象出一个最基本的数据结构

@Data
public class DataPacket {

    protected Header header = new Header(); //消息头
    protected ByteBuf byteBuf; //消息流

    @Data
    public static class Header {
        private short msgId;// 消息ID 2字节
        private short msgBodyProps;//消息体属性 2字节
        private String terminalPhone; // 终端手机号 6字节
        private short flowId;// 流水号 2字节

        //获取包体长度
        public short getMsgBodyLength() {
            return (short) (msgBodyProps & 0x3ff);
        }

        //获取加密类型 3bits
        public byte getEncryptionType() {
            return (byte) ((msgBodyProps & 0x1c00) >> 10);
        }

        //是否分包
        public boolean hasSubPackage() {
            return ((msgBodyProps & 0x2000) >> 13) == 1;
        }
    }
}

我们可以先将Header解析出来,然后由子类自己解析包体

 public void parse() {
        try{
            this.parseHead();
            //验证包体长度
            if (this.header.getMsgBodyLength() != this.byteBuf.readableBytes()) {
                throw new RuntimeException("包体长度有误");
            }
            this.parseBody();//由子类重写
        }finally {
            ReferenceCountUtil.safeRelease(this.byteBuf);//注意释放
        }
    }

    protected void parseHead() {
        header.setMsgId(byteBuf.readShort());
        header.setMsgBodyProps(byteBuf.readShort());
        header.setTerminalPhone(BCD.BCDtoString(readBytes(6)));
        header.setFlowId(byteBuf.readShort());
    }
    protected void parseBody() {

    }

其中readByte(int length)方法是对ByteBuf.readBytes(byte[] dst)的一个简单封装

public byte[] readBytes(int length) {
        byte[] bytes = new byte[length];
        this.byteBuf.readBytes(bytes);
        return bytes;
}

因为没有在Netty官方的Api中找到类似的方法,所以自己定义了一个

另外定义一个方法用于响应重写。

响应重写:

 public ByteBuf toByteBufMsg() {
        ByteBuf bb = ByteBufAllocator.DEFAULT.heapBuffer();
        bb.writeInt(0);//先占4字节用来写msgId和msgBodyProps
        bb.writeBytes(BCD.toBcdBytes(StringUtils.leftPad(this.header.getTerminalPhon
  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 38
    评论
评论 38
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值