基于Netty实现高性能通信程序之传输协议编码与解码
1、协议抽象实体
1 package protocal.model; 2 3 import lombok.Data; 4 5 /** 6 * @author liupengr 7 * @date 2020/2/12 18:21 8 */ 9 @Data 10 public abstract class AbstractProtocalEntity { 11 12 /** 13 * 获取序列化工具由子类实现 14 * 15 * @return 16 */ 17 public abstract Byte getSerializerType(); 18 19 /** 20 * 获取操作指令 21 * @return 22 */ 23 public abstract Byte getCommand(); 24 25 /** 26 * 协议版本号 27 */ 28 private Byte version = 1; 29 30 31 }
2、业务操作实体(信息传递)
1 package protocal.model; 2 3 import lombok.AllArgsConstructor; 4 import lombok.Data; 5 import lombok.EqualsAndHashCode; 6 import lombok.NoArgsConstructor; 7 import serializer.service.SerializerEnum; 8 9 /** 10 * 消息传输实体 11 * 12 * @author liupengr 13 * @date 2020/2/12 18:38 14 */ 15 @Data 16 @NoArgsConstructor 17 @AllArgsConstructor 18 @EqualsAndHashCode(callSuper = true) 19 public class MsgEntity extends AbstractProtocalEntity { 20 21 /** 22 * 序号:TCP 连接它是一个全双工的通道,同时进行数据的双向收发,此时就需要序号来使请求和响应对应 23 */ 24 private Integer num; 25 26 /** 27 * 会话ID 28 */ 29 private Integer session; 30 31 /** 32 * 用户ID 33 */ 34 private Integer userId; 35 36 /** 37 * 内容 38 */ 39 private String content; 40 41 /** 42 * 得到当前传输实体的编码格式 43 * 44 * @return 45 */ 46 @Override 47 public Byte getSerializerType() { 48 return SerializerEnum.PROTOSTUFF.getCode().byteValue(); 49 } 50 51 /** 52 * 获取当前传输实体的操作标识 53 * 54 * @return 55 */ 56 @Override 57 public Byte getCommand() { 58 return Contrast.Msg; 59 } 60 61 }
3、常量类
1 package protocal.model; 2 3 import java.util.HashMap; 4 5 /** 6 * 7 * @author liupengr 8 * @date 2020/2/12 18:41 9 */ 10 public class Contrast { 11 12 public static final HashMap<Byte, Class> commondMap; 13 public static final byte Msg = 1; 14 15 static { 16 commondMap = new HashMap<>(); 17 commondMap.put(Msg, MsgEntity.class); 18 } 19 20 21 }
4、解码与编码
1 package protocal; 2 3 import io.netty.buffer.ByteBuf; 4 import io.netty.buffer.ByteBufAllocator; 5 import protocal.model.AbstractProtocalEntity; 6 import protocal.model.Contrast; 7 import serializer.impl.SerializerFactory; 8 import serializer.service.Serializer; 9 import serializer.service.SerializerEnum; 10 11 /** 12 * <br/> 13 * 通信协议 14 * 魔数0x12345678(4字节)|版本号(1字节)|序列化算法(1字节)|指令(1字节)|数据长度(4字节)|数据(N字节) 15 * 16 * @author liupengr 17 * @date 2020/2/12 18:49 18 */ 19 public class protocalProcess { 20 21 private static final int MAGIC_NUMBER = 0x12345678; 22 23 public ByteBuf encode(AbstractProtocalEntity entity) { 24 // 1. 创建 ByteBuf 对象 25 ByteBuf byteBuf = ByteBufAllocator.DEFAULT.ioBuffer(); 26 // 2. 序列化 Java 对象 27 byte[] bytes = getSerializer(entity.getSerializerType()).serialize(entity); 28 // 3. 实际编码过程 29 byteBuf.writeInt(MAGIC_NUMBER); 30 byteBuf.writeByte(entity.getVersion()); 31 byteBuf.writeByte(entity.getSerializerType()); 32 byteBuf.writeByte(entity.getCommand()); 33 byteBuf.writeInt(bytes.length); 34 byteBuf.writeBytes(bytes); 35 36 return byteBuf; 37 } 38 39 public AbstractProtocalEntity decode(ByteBuf byteBuf) { 40 // 跳过 magic number 41 byteBuf.skipBytes(4); 42 // 跳过版本号 43 byteBuf.skipBytes(1); 44 // 序列化算法标识 45 byte serializeType = byteBuf.readByte(); 46 // 指令 47 byte command = byteBuf.readByte(); 48 // 数据包长度 49 int length = byteBuf.readInt(); 50 byte[] bytes = new byte[length]; 51 byteBuf.readBytes(bytes); 52 Class<? extends AbstractProtocalEntity> requestType = Contrast.commondMap.get(command); 53 Serializer serializer = getSerializer(serializeType); 54 if (requestType != null && serializer != null) { 55 return serializer.deserialize(requestType, bytes); 56 } 57 58 return null; 59 } 60 61 private Serializer getSerializer(Byte type) { 62 return SerializerFactory.getSerializerInstance(SerializerEnum.valueOf(type)); 63 } 64 }
Don’t hurry say have no choice, perhaps, next intersection will meet hope.