使用Netty绑定一个端口如何分辨出多种类型的DTU的注册包

1、  背景

项目须要使用NettyDTU(无线数据传输模块)通讯,须要接入多种类型的DTU,每种dtu链接上来以后都首先会发送一个注册报文。须要解析该注册报文来实现: ide

1. 分辨出是哪一种类型的dtu 工具

2. 从注册报文中识别出注册码,以便决定该dtu下面链接的是哪一个装置。 this

问题在于这是两个不一样厂家的DTU,他们的注册报文的内容和长度都不相同。此时咱们就没法使用诸如DelimitedBasedFrameDecoderFixedLengthFrameDecoder这样现成的工具类来解决粘包的问题,须要本身去解析收到的每一个字节,而后分别是判断对应的报文是哪一种DTU的注册报文,把不一样种类的注册包解析成内部消息。 spa

public class DtuLoginMessage { code

    public enum DtuType{ orm

       dtJingfuyuan, 继承

       dtTopIot get

    } it

   

    private DtuType dtuType; io

    private String regCode;

   

    public DtuType getDtuType() {

       return dtuType;

    }

 

    public String getRegCode() {

       return regCode;

    }  

   

    public DtuLoginMessage(DtuType type, String regCode){

       this.dtuType = type;

       this.regCode = regCode;

    }

}

 

 2、解决方案

既然没法没法使用工具类来解决粘包、拆包的问题,那就须要本身去解析每一个字节,那就要自定义一个ChannelHandler子类来说随机收到的ByteBuf转换为DtuLoginMessage,咱们通常写ChannelHandler都是直接继承自ChannelInboundHandlerAdapter,而后去override他的channelRead方法,若是直接用这个类也不是不行,可是那就意味着本身要定义一个缓冲区来接受每次channelRead传递过来的字节,每次有新的字节过来,就要先写入到缓冲区,而后再去检查一下当前缓冲区的这些数据是否已是某个dtu的注册包了,若是是的话就能够日后走了。这里存在的主要问题是要本身去维护这个缓冲区,若是有什么工具类能够帮咱们维护就更好了,记得曾经在哪里看过。

没错,ByteToMessageDecoder就是干这活的,可让本身的Handler继承ByteToMessageDecoder,而后重写其中的decode方法,该方法的签名以下,实例代码以下:

protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {    

DtuLoginMessage loginMsg = DtuLoginHandlerContainer.getInstance().decode(in);      

        if (loginMsg != null)

            out.add(loginMsg);

}

 

每次decode被调用,都去检查一下是不是某个dtu的注册包,若是是,就添加到out中;若是不是,那就什么都不用管,这样下次decode被调用的时候还会包含以前全部没有被解析的字节内容。



相关文章
相关标签/搜索