使用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被調用的時候還會包含以前全部沒有被解析的字節內容。



相關文章
相關標籤/搜索