基于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 }
VAbstractProtocalEntity

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 }
class MsgEntity extends AbstractProtocalEntity

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 }
Contrast

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 }
protocalProcess

 

posted @ 2020-02-12 19:22  以梦为码  阅读(462)  评论(0编辑  收藏  举报