• 基于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
  • 相关阅读:
    Android 调用浏览器和嵌入网页
    Android Fragment间对象传递
    Android Volley获取json格式的数据
    git无法clone远程代码库及git代理设置
    Android Studio在线安装Android SDK注意事项
    【转】如何修改Chrome缓存目录的地址
    【转】MySQL Temporary Table相关问题的探究
    Android读写assets、raw、sdard和工程文件的方法
    Android简易数据存储之SharedPreferences
    (转) Deep Learning in a Nutshell: Core Concepts
  • 原文地址:https://www.cnblogs.com/volare/p/12300423.html
Copyright © 2020-2023  润新知