package cc.ak.tcp.codec;
//import com.zw.admin.server.utils.HexConvertUtil;
import cc.ak.utils.HexConvertUtil;
import cn.hutool.core.util.ArrayUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.internal.logging.InternalLoggerFactory;
import lombok.extern.slf4j.Slf4j;
import javax.lang.model.element.VariableElement;
import java.util.List;
/**
* 自定义解码器
*
* @author jie
*/
@Slf4j
public class CustomDecoder extends ByteToMessageDecoder {
// InternalLoggerFactory.setDefaultFactory(new Log4JLoggerFactory());
// 我们定义的是前六位是一个包的包头 所以判断的话一般根据前六位来判断是不是我们的包,从而获取报的长度来进行截取,避免粘包
public static final int MBAP_LEN = 6;
public static final int MAX_LEN = 2000;
/**
* 十六进制字符串数组解析
*
* @param channelHandlerContext
* @param in 传入数据
* @param list 添加解码消息
* @throws Exception
*/
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> list) throws Exception {
ByteBuf copy = in.copy();
if (copy.readableBytes() < MBAP_LEN) {
//将消息清除掉
in.readBytes(in.readableBytes());
return;
}
//数据包过长就会将数据包丢弃
// 标记一下当前的readIndex的位置
int beginIndex = copy.readerIndex();
//读取报文头MBAP
ByteBuf buf = copy.readBytes(MBAP_LEN);
byte[] dst = new byte[MBAP_LEN];
buf.readBytes(dst);
//判断是否是ModbusTCP协议
if (dst[2] != 0x00 || dst[3] != 0x00) {
//读取所有消息 防止消息累积
in.readBytes(in.readableBytes());
in.discardReadBytes();
return;
}
//获取MBAP中的数据体长度
long len = HexConvertUtil.hexByteToLong(new byte[]{dst[4], dst[5]});
//报文长度小于数据体长度
int readLen = copy.readableBytes();
if (readLen < len) {
if(len > MAX_LEN){
//大于最大长度这个包舍弃
in.readBytes(in.readableBytes());
in.discardReadBytes();
}
//重置索引
copy.readerIndex(beginIndex);
System.out.println("查看未发送的字节长度"+in.readableBytes());
return;
}
ByteBuf message = in.readBytes((int) (MBAP_LEN+len));
byte[] bytes = new byte[(int) (MBAP_LEN+len)];
message.readBytes(bytes);
//将数组合并
String hexMessage = ByteBufUtil.hexDump(bytes);
log.info("接收的指令"+hexMessage);
System.out.println("要去下一个地方了");
list.add(hexMessage);
}
}
netty 初体验 自定义解码器
最新推荐文章于 2025-03-29 11:09:53 发布
本文档介绍了如何实现一个自定义的ByteToMessageDecoder,用于解析ModbusTCP协议的数据包,包括MBAP头判断、长度计算、粘包处理和消息解码。重点讲解了包头的判断逻辑和数据体的正确截取方式。
855

被折叠的 条评论
为什么被折叠?



