mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-04-20 11:05:18 +08:00
update 重构
This commit is contained in:
@@ -0,0 +1,96 @@
|
|||||||
|
package com.jsowell.netty.decoder;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
||||||
|
import io.netty.handler.codec.DecoderException;
|
||||||
|
|
||||||
|
public class CustomLengthFieldBasedFrameDecoder extends LengthFieldBasedFrameDecoder {
|
||||||
|
|
||||||
|
private static final int MAX_FRAME_LENGTH = 256; // 最大帧长度
|
||||||
|
private static final int LENGTH_FIELD_OFFSET = 1; // 数据长度字段的偏移位置
|
||||||
|
private static final int LENGTH_FIELD_LENGTH = 1; // 数据长度字段占的字节数
|
||||||
|
|
||||||
|
public CustomLengthFieldBasedFrameDecoder() {
|
||||||
|
super(MAX_FRAME_LENGTH, LENGTH_FIELD_OFFSET, LENGTH_FIELD_LENGTH, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object decode(io.netty.channel.ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
|
||||||
|
if (buffer.readableBytes() < 5) {
|
||||||
|
return null; // 至少要有起始标志(1字节) + 数据长度(1字节) + 序列号域(2字节)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验起始标志是否为0x68
|
||||||
|
byte startFlag = buffer.getByte(buffer.readerIndex());
|
||||||
|
if (startFlag != (byte) 0x68) {
|
||||||
|
throw new DecoderException("Invalid start flag, expected 0x68 but got 0x" + Integer.toHexString(startFlag));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算数据长度
|
||||||
|
buffer.skipBytes(1); // 跳过起始标志
|
||||||
|
byte dataLength = buffer.readByte(); // 读取数据长度字段
|
||||||
|
|
||||||
|
// 如果数据长度大于实际可读取的字节数,返回 null 等待更多数据
|
||||||
|
if (buffer.readableBytes() < dataLength) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取序列号域、加密标志、帧类型标志、消息体和帧校验域
|
||||||
|
short serialNumber = buffer.readShort(); // 读取序列号域(2字节)
|
||||||
|
byte encryptFlag = buffer.readByte(); // 读取加密标志(1字节)
|
||||||
|
byte frameTypeFlag = buffer.readByte(); // 读取帧类型标志(1字节)
|
||||||
|
ByteBuf messageBody = buffer.readBytes(dataLength - 6); // 读取消息体数据(数据长度 - 6字节)
|
||||||
|
|
||||||
|
// 读取并校验帧校验域(CRC)
|
||||||
|
short expectedCrc = buffer.readShort(); // 读取校验域(2字节)
|
||||||
|
|
||||||
|
// 校验 CRC
|
||||||
|
short actualCrc = calculateCrc(serialNumber, encryptFlag, frameTypeFlag, messageBody);
|
||||||
|
if (actualCrc != expectedCrc) {
|
||||||
|
throw new DecoderException("CRC mismatch, expected: " + Integer.toHexString(expectedCrc) + ", but got: " + Integer.toHexString(actualCrc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造并返回完整的数据包对象
|
||||||
|
return new CustomMessage(serialNumber, encryptFlag, frameTypeFlag, messageBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRC 校验计算方法
|
||||||
|
private short calculateCrc(short serialNumber, byte encryptFlag, byte frameTypeFlag, ByteBuf messageBody) {
|
||||||
|
// CRC 计算可以使用指定的 CRC 多项式 0x180D 进行计算
|
||||||
|
// 这里可以实现 CRC 校验的具体计算逻辑,返回计算得到的 CRC 值
|
||||||
|
// 简单示范,这里返回一个默认值,实际应根据具体协议计算
|
||||||
|
return (short) 0xFFFF; // 这里只是一个示例值,实际要根据数据进行计算
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自定义消息类,包含协议解析后的字段
|
||||||
|
public static class CustomMessage {
|
||||||
|
private short serialNumber;
|
||||||
|
private byte encryptFlag;
|
||||||
|
private byte frameTypeFlag;
|
||||||
|
private ByteBuf messageBody;
|
||||||
|
|
||||||
|
public CustomMessage(short serialNumber, byte encryptFlag, byte frameTypeFlag, ByteBuf messageBody) {
|
||||||
|
this.serialNumber = serialNumber;
|
||||||
|
this.encryptFlag = encryptFlag;
|
||||||
|
this.frameTypeFlag = frameTypeFlag;
|
||||||
|
this.messageBody = messageBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter 方法
|
||||||
|
public short getSerialNumber() {
|
||||||
|
return serialNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getEncryptFlag() {
|
||||||
|
return encryptFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getFrameTypeFlag() {
|
||||||
|
return frameTypeFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuf getMessageBody() {
|
||||||
|
return messageBody;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.jsowell.netty.decoder;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义LengthFieldBasedFrameDecoder
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class MyLengthFieldBasedFrameDecoder extends LengthFieldBasedFrameDecoder {
|
||||||
|
/*
|
||||||
|
构造方法
|
||||||
|
maxFrameLength:指定解码器所能处理的数据包的最大长度,超过该长度则抛出 TooLongFrameException 异常;
|
||||||
|
lengthFieldOffset:指定长度字段的起始位置;
|
||||||
|
lengthFieldLength:指定长度字段的长度:目前支持1(byte)、2(short)、3(3个byte)、4(int)、8(Long)
|
||||||
|
lengthAdjustment:指定长度字段所表示的消息长度值与实际长度值之间的差值,可以用于调整解码器的计算和提高灵活性。
|
||||||
|
initialBytesToStrip:指定解码器在将数据包分离出来后,跳过的字节数,因为这些字节通常不属于消息体内容,而是协议头或其他控制信息。
|
||||||
|
lengthAdjustment(可正可负)需要满足以下的计算关系:
|
||||||
|
*/
|
||||||
|
public MyLengthFieldBasedFrameDecoder() {
|
||||||
|
super(208, 1, 1, 0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
|
||||||
|
return super.decode(ctx, in);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.jsowell.netty.server.yunkuaichong;
|
package com.jsowell.netty.server.yunkuaichong;
|
||||||
|
|
||||||
import com.jsowell.netty.decoder.StartAndLengthFieldFrameDecoder;
|
import com.jsowell.netty.decoder.CustomLengthFieldBasedFrameDecoder;
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.socket.SocketChannel;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
@@ -21,7 +21,8 @@ public class NettyServerChannelInitializer extends ChannelInitializer<SocketChan
|
|||||||
protected void initChannel(SocketChannel channel) throws Exception {
|
protected void initChannel(SocketChannel channel) throws Exception {
|
||||||
ChannelPipeline pipeline = channel.pipeline();
|
ChannelPipeline pipeline = channel.pipeline();
|
||||||
// pipeline.addLast("frameDecoder",new CustomDecoder());
|
// pipeline.addLast("frameDecoder",new CustomDecoder());
|
||||||
pipeline.addLast("frameDecoder", new StartAndLengthFieldFrameDecoder());
|
// pipeline.addLast("frameDecoder", new StartAndLengthFieldFrameDecoder());
|
||||||
|
pipeline.addLast("frameDecoder", new CustomLengthFieldBasedFrameDecoder());
|
||||||
pipeline.addLast("decoder", new ByteArrayDecoder());
|
pipeline.addLast("decoder", new ByteArrayDecoder());
|
||||||
pipeline.addLast("encoder", new ByteArrayDecoder());
|
pipeline.addLast("encoder", new ByteArrayDecoder());
|
||||||
//读超时时间设置为10s,0表示不监控
|
//读超时时间设置为10s,0表示不监控
|
||||||
|
|||||||
Reference in New Issue
Block a user