Netty的自定义协议解码器
做了使用一个接收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;
}
//下面就可以开始依据协议对数据进行解析了
}

浙公网安备 33010602011771号