| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- package com.jttserver.codec;
- import io.netty.buffer.ByteBuf;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.handler.codec.ByteToMessageDecoder;
- import java.util.List;
- import com.jttserver.protocol.JttConstants;
- /**
- * JTT1078协议消息解码器
- * 处理TCP粘包和拆包问题
- */
- public class Jtt1078MessageDecoder extends ByteToMessageDecoder {
- // JTT1078数据包标识 0x30316364
- private static final int PACKET_HEADER = 0x30316364;
- private static final int MIN_DATA_LENGTH = 19; //最小为透传数据18+1个字节
- private static final int MIN_HEADER_LENGTH = 18;
- private static final int MAX_HEADER_LENGTH = 30;
- private final int jtt808Type;
- private int jttOffset = 0; // JTT808协议偏移量,2013版为0,2019版为4 设备sim的BCD字段多占4字节
- // 默认构造函数,使用JTT808 2013版
- public Jtt1078MessageDecoder() {
- this.jtt808Type = JttConstants.TYPE_JTT808_2013;
- }
- public Jtt1078MessageDecoder(int jtt808Type) {
- this.jtt808Type = jtt808Type;
- if (this.jtt808Type == JttConstants.TYPE_JTT808_2019) {
- jttOffset = 4;
- }
- }
- @Override
- protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
- // 循环处理,直到没有完整数据包可读(至少需要最小头部长度+NALU数据长度)
- while (in.isReadable(MIN_DATA_LENGTH + jttOffset)) {
- // 查找数据包头部
- int headerIndex = findHeader(in);
- if (headerIndex == -1) {
- // 没有找到头部,等待更多数据
- return;
- }
- // 跳过无效数据到头部位置
- if (headerIndex > 0) {
- // System.out.println("Jtt1078MessageDecoder: 跳过了 " + headerIndex + " 个无效字节");
- in.skipBytes(headerIndex);
- }
- // 确保有足够的数据进行头部解析
- if (in.readableBytes() < MIN_HEADER_LENGTH + jttOffset) {
- return;
- }
- // 读取头部标识
- int header = in.readInt();
- if (header != PACKET_HEADER) {
- throw new IllegalStateException("Header mismatch after sync");
- }
- // 确保有足够的数据读取到第15字节(已经读取了4字节header)
- if (in.readableBytes() < 12 + jttOffset) {
- in.resetReaderIndex();
- return;
- }
- // 跳过前11字节到达第15字节 (已读取4字节header,还需跳过11字节到达第15字节)
- in.skipBytes(11 + jttOffset);
- // 读取第15字节并获取前4位
- byte fifteenthByte = in.readByte();
- int first4Bits = (fifteenthByte & 0xF0) >> 4;
- // 根据前4位确定包头长度
- int headerLength;
- switch (first4Bits) {
- case 0x0: // 0000
- case 0x1: // 0001
- case 0x2: // 0010
- headerLength = MAX_HEADER_LENGTH + jttOffset;
- break;
- case 0x3: // 0011
- headerLength = 26 + jttOffset;
- break;
- case 0x4: // 0100
- headerLength = 18 + jttOffset;
- break;
- default:
- // 未知类型, 报错
- throw new IllegalStateException("Nalu type unknow!");
- }
- // 回到包头开始位置
- in.readerIndex(in.readerIndex() - 16 - jttOffset); // 回退16字节
- // 确保有足够的数据读取整个包头
- if (in.readableBytes() < headerLength) {
- return;
- }
- // 跳到包头最后2个字节的位置读取数据长度 (使用大端序)
- in.skipBytes(headerLength - 2);
- int dataLength = in.readUnsignedShort(); // 使用大端序读取
- // 计算整个包长度
- int totalLength = headerLength + dataLength;
- // 回到包开始位置 (头部标识位置)
- in.readerIndex(in.readerIndex() - headerLength); // 回退到头部开始位置
- // 检查是否有足够的数据构成完整的消息
- if (in.readableBytes() < totalLength) {
- return;
- }
- // 读取完整数据包(包括包头和数据)
- byte[] packet = new byte[totalLength];
- in.readBytes(packet);
- // 将解码后的完整数据包添加到输出列表
- out.add(packet);
- }
- }
- /**
- * 在缓冲区中查找JTT1078数据包头部
- *
- * @param buffer 输入缓冲区
- * @return 头部位置,未找到返回-1
- */
- private int findHeader(ByteBuf buffer) {
- // 创建搜索用的头部字节数组
- byte[] headerBytes = new byte[] {
- (byte) ((PACKET_HEADER >> 24) & 0xFF),
- (byte) ((PACKET_HEADER >> 16) & 0xFF),
- (byte) ((PACKET_HEADER >> 8) & 0xFF),
- (byte) (PACKET_HEADER & 0xFF)
- };
- // 保存当前读索引
- int originalReaderIndex = buffer.readerIndex();
- // 在可读范围内搜索头部
- for (int i = 0; i <= buffer.readableBytes() - 4; i++) {
- boolean found = true;
- for (int j = 0; j < 4; j++) {
- byte b = buffer.getByte(originalReaderIndex + i + j);
- if (b != headerBytes[j]) {
- found = false;
- break;
- }
- }
- if (found) {
- return i;
- }
- }
- return -1;
- }
- }
|