Netty的自定義協議解碼器
阿新 • • 發佈:2021-08-20
做了使用一個接收stm32微控制器資料的專案,其中用到了netty自定義協議解碼器,在此記錄一下
- 自定義協議解碼器繼承ByteToMessageDecoder
- 當bytebuf不包含整個協議訊息長度時需要 return,直到bytebuf的長度包含整個協議的長度時,再進行解析
- stm32是小端資料,接收的時需要考慮大小端問題
- 當協議使用CRC32校驗時,需注意stm的CRC32和主流CRC32有所不同,而且還有注意資料大小端問題。具體參考這篇文章
下面是部分程式碼
public class MyProtocolByteDecoder extends ByteToMessageDecoder { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println(ctx.channel().remoteAddress().toString()); } @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { Object decoded = this.decode(ctx, in); if (decoded != null && !decoded.equals("")) { out.add(decoded); } } protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { //防止byteBuf過大,超過最大值時清理 clearRead(in); //訊息小於接收的最小長度 if (in.readableBytes() < 33) { return null; } //防止socket位元組流攻擊、客戶端傳來的資料過大,這裡需要對資料進行過濾掉 if(in.readableBytes() >= 40960){ in.skipBytes(in.readableBytes()); return null; } //記錄訊息頭部位置 int beginIndex; while (true) { beginIndex = in.readerIndex(); //記錄包頭開始位置 //in.markReaderIndex(); //標記包頭開始index //讀取協議開始標誌 //讀取幀頭欄位 0-1 short i = in.readShort(); if((short)30959== i){ break; //如果是開始標記,那麼就結束查詢 } //如果讀完了所有的資料 都沒有獲取到 訊息頭部 則判定所有訊息為無效訊息,直接放棄掉 if (in.readableBytes() == 0) { return null; } } //資料型別 2 可以接收兩種不同長度的資料 byte type = in.readByte(); int msgLength = 0; if (type ==1 ){ msgLength = 3244; }else if (type ==2){ msgLength = 28672; } //訊息長度 這裡已經讀了三個位元組所以要加3 int i2 = in.readableBytes(); if ( in.readableBytes()+3< msgLength) { //訊息長度不夠,還原readerIndex到訊息頭部的位置 in.readerIndex(beginIndex); return null; } //下面就可以開始依據協議對資料進行解析了 }