看啥推荐读物
专栏名称: xuexiangjys
Android架构师
今天看啥  ›  专栏  ›  xuexiangjys

XTCP 一个便捷的TCP消息包拼装和解析框架

xuexiangjys  · 掘金  · android  · 2018-12-18 06:56
阅读 8

XTCP 一个便捷的TCP消息包拼装和解析框架

XTCP

xtcp
api

一个便捷的TCP消息包拼装和解析框架

关于我

github
csdn

特征

  • 简单通过@Protocol@ProtocolField的配置,即可让实体对象拥有自动转化为TCP传输的byte数据和自动byte数据解析。

  • 支持byte、short、int、long、byte[]、short[]、int[]、long[]、String等常用基础类型,支持类型的拓展

  • 支持大端和小端两种存储方式,支持设置全局默认存储方式和局部存储方式。

  • 支持short、int、long读取长度的自定义。

  • 支持对实体字段进行排序,避免解析错乱。

  • 支持自定义协议项和协议解析器。

  • 支持自动协议映射,自动根据读取的opcode识别出对应的协议并进行解析,并根据对应注册的协议信息判断协议是否有响应。


1、演示(请star支持)

Demo下载

downloads
在这里插入图片描述

2、如何使用

目前支持主流开发工具AndroidStudio的使用,直接配置build.gradle,增加依赖即可.

2.1 添加Gradle依赖

1.先在项目根目录的 build.gradle 的 repositories 添加:

allprojects {
     repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}
复制代码

2.然后在dependencies添加:

dependencies {
  ...
  implementation 'com.github.xuexiangjys.XTCP:xtcp_runtime:1.0.0'
  annotationProcessor 'com.github.xuexiangjys.XTCP:xtcp_compiler:1.0.0'
}
复制代码

3.进行moduleName注册

defaultConfig {
    ...

    javaCompileOptions {
        annotationProcessorOptions {
            arguments = [ moduleName : project.getName() ]
        }
    }
}
复制代码

【注意】:如果不注册的话,默认ModuleName为app

2.2 初始化协议中心

在Application中注册协议中心和协议字段中心。

XTCP.getInstance()
        .addIProtocolCenter(AppProtocolCenter.getInstance()) //添加协议中心
        .addIProtocolFieldCenter(AppProtocolFieldCenter.getInstance(), XTCPProtocolFieldCenter.getInstance()) //添加协议字段中心
        .setDefaultStorageMode(StorageMode.BigEndian) //设置默认存储方式(默认是大端)
        .debug(true); //打开调试日志
复制代码

2.3 构建通信协议实体

通过继承XProtocolItem或者实现IProtocolItem接口,通过@Protocol@ProtocolField注解进行配置。

  • @Protocol: 用于注解协议项,包括nameopcoderesCodemodedesc等属性。

  • @ProtocolField: 用于注解协议项字段,包括indexisFieldlengthmodecharset等属性。

@Protocol(name = "参数设置请求", opCode = 0x12, resCode = 0x33, desc = "注意重启下位机后生效!")
public class SettingRequest extends XProtocolItem {
    @ProtocolField(index = 0)
    private byte func1;
    @ProtocolField(index = 1)
    private short func2;
    @ProtocolField(index = 2)
    private int func3;
    @ProtocolField(index = 3)
    private long func4;
    @ProtocolField(index = 4)
    private ByteArray list1;
    @ProtocolField(index = 5)
    private ShortArray list2;
    @ProtocolField(index = 6)
    private IntArray list3;
    @ProtocolField(index = 7)
    private LongArray list4;
    @ProtocolField(index = 8)
    private StringField string1;
    @ProtocolField(index = 9)
    private LargeString string2;
    @ProtocolField(index = 10)
    private TestProtocolItem testItem;
    @ProtocolField(index = 11)
    private LoginInfo loginInfo;
    @ProtocolField(index = 12)
    private LoginInfoArray loginInfos;
}
复制代码

2.4 自定义协议项和协议项数组

自定义协议项

要想自定义协议项很简单,同样的,只需要继承XProtocolItem或者实现IProtocolItem接口,使用@ProtocolField注解进行配置即可。

【注意】不需要使用@Protocol进行注解。

public class LoginInfo extends XProtocolItem {
    @ProtocolField(index = 0)
    private StringField loginName;

    @ProtocolField(index = 1)
    private StringField password;
}

复制代码

自定义协议项数组

自定义协议项数组类需要继承AbstractArrayItem,详细的实现案例点击查看

2.5 协议项的byte化和反byte化

凡是继承XProtocolItem或者实现IProtocolItem接口,都将有如下两个方法:

/**
 * 将协议实体转化为byte数组
 *
 * @param storageMode 存储形式
 * @return
 */
byte[] proto2byte(StorageMode storageMode);

/**
 * 将byte数组数据转化为协议实体
 *
 * @param bytes       byte数组数据
 * @param index       起始字节
 * @param tailLength  消息尾的长度[和index一起决定了数据解析的范围]
 * @param storageMode 存储形式
 * @return 是否解析成功
 */
boolean byte2proto(byte[] bytes, int index, int tailLength, StorageMode storageMode);
复制代码

使用案例如下:

SettingRequest request = new SettingRequest()
        .setFunc1((byte) 0x45)
        .setFunc2((short) 12)
        .setFunc3(2345)
        .setFunc4((long) 1213131233)
        .setList1((byte) 0x23, (byte) 0x45, (byte) 0x56)
        .setList2((short) 11, (short) 22, (short) 33)
        .setList3(111, 222, 333)
        .setList4((long) 1221312, (long) 23123123)
        //长度超过255的话,就溢出了
        .setString1("我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!")
        .setString2("我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!" +
                "我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!" +
                "我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!" +
                "我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!" +
                "我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!" +
                "我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!" +
                "我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!我的名字叫薛翔!")
        .setLoginInfo(new LoginInfo("xuexiang", "123456"))
        .setLoginInfos(new LoginInfo("xuexiang1", "222"),
                new LoginInfo("xuexiang23", "3333"),
                new LoginInfo("xuexiang456", "44444"))
        .setTestItem(new TestProtocolItem()
                .setFunc1((byte) 0x56)
                .setFunc2((short) 314)
                .setFunc3(6111)
                .setFunc4((long) 35536234)
                .setList1(314, 334, 34235, 67584, 45234, 6757)
                .setLoginInfo(new LoginInfo("xuexiangjys", "111111")));
byte[] bytes = request.proto2byte(StorageMode.Default);
Log.e("xuexiang", ConvertUtils.bytesToHexString(bytes));

SettingRequest request1 = new SettingRequest();
request1.byte2proto(bytes, 0, 0, StorageMode.Default);

Log.e("xuexiang", request1.toString());
复制代码

2.6 消息体包装与解析

实现IMessage接口,可自定义属于自己的协议消息载体。框架中默认提供了XMessageXOrderlyMessage两种消息体模版。

消息转byte的使用方法

  • 1.新建你需要使用的消息体模版。

  • 2.设置你传输的协议项。

  • 3.使用msg2Byte方法将消息转化为byte数组数据。

byte转消息的使用方法

  • 1.新建你需要转化的消息体模版。

  • 2.使用byte2Msg方法,传入byte数组数据进行转化。

MessageTest messageTest = new MessageTest()
        .setFunc1((byte) 0x45)
        .setFunc2((short) 12)
        .setFunc3(2345)
        .setFunc4((long) 1213131233)
        .setList2((short) 11, (short) 22, (short) 33)
        .setLoginInfo(new LoginInfo("xuexiang", "123456"));

XMessage message = new XMessage()
        .setIProtocolItem(messageTest);
byte[] bytes = message.msg2Byte();
Log.e("xuexiang", ConvertUtils.bytesToHexString(bytes));

XMessage message1 = new XMessage();
boolean result = message1.byte2Msg(bytes);

Log.e("xuexiang", "result:" + result +", ProtocolItem:" + message1.getProtocolItem());
复制代码

2.7 自定义协议解析器

如果你对协议的解析有特殊的需求,可实现IProtocolParser接口,并通过XTCP.getInstance().setIProtocolParser来替换默认的协议解析器

【注意】谨慎替换,如果替换方法有误的话,会导致整个框架无法正常使用,建议不要替换。


3、基础内容介绍

协议项注解@Protocol

属性名 类型 默认值 备注
name String "" 协议的名称
opCode byte /(必填) 协议命令码,协议命令的唯一号
resCode byte -1 协议响应码(结果对应的命令码)
mode StorageMode StorageMode.Default 数据存储方式(大端 or 小端)
desc String "" 描述信息

协议字段注解@ProtocolField

属性名 类型 默认值 备注
index int /(必填) 字段的顺序索引
isField boolean true 是否为协议解析字段
length int -1 协议字段的长度, 不设置的话,默认自动识别
mode StorageMode StorageMode.Default 数据存储方式(大端 or 小端)
charset String "UTF-8" 字符集(只对String有效)

基础数组数据类型

类名 对应的数组类型 数组最大长度
ByteArray byte[] 255
LargeByteArray byte[] 65535
IntArray int[] 255
ShortArray short[] 255
LongArray long[] 255
StringField String 255
LargeString String 65535

4、混淆配置

# xtcp
-keep @com.xuexiang.xtcp.annotation.* class * {*;}
-keep class * {
    @com.xuexiang.xtcp.annotation.* <fields>;
}
-keepclassmembers class * {
    @com.xuexiang.xtcp.annotation.* <methods>;
}
复制代码

联系方式

在这里插入图片描述




原文地址:访问原文地址
快照地址: 访问文章快照