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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: XTCP 一个便捷的TCP消息包拼装和解析框架

XTCP


项目地址: github.com/xuexiangjys…, 喜欢的欢迎star收藏!~~


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


特征


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


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


  • 支持无符号数和有符号数两种。


  • 支持BCD编码格式【时间、int、float、double等】。


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


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


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


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


  • 支持对不定长数组解析【需要注意的是,在一条协议中有且只能有一个不定长的数组,否则将无法解析成功】。


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


1、演示(请star支持)


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.7'
  annotationProcessor 'com.github.xuexiangjys.XTCP:xtcp_compiler:1.0.7'
}


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 BCD<Date> time = new BCD<>(Date.class, "yy-MM-dd HH:mm:ss");
    @ProtocolField(index = 13)
    private BCD<Integer> number = new BCD<>(Integer.class, "XXX");
    @ProtocolField(index = 14)
    private BCD<Float> total = new BCD<>(Float.class, "XXXXX.XX");
    @ProtocolField(index = 15)
    private BCD<Double> money = new BCD<>(Double.class, "XXXXX.XX");
    @ProtocolField(index = 16)
    private FixedString ID = new FixedString(10);
    @ProtocolField(index = 17)
    private LoginInfoArray loginInfos;
    @ProtocolField(index = 18, unsigned = false)
    private short signedShort;
    @ProtocolField(index = 19, unsigned = false)
    private int signedInt;
    @ProtocolField(index = 20, unsigned = false)
    private long signedLong;
}


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"))
        .setTime(new Date())
        .setNumber(123)
        .setTotal(12345.67F)
        .setMoney(23456.78)
        .setID("1234567890")
        .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")))
        .setSignedShort((short) -678)
        .setSignedInt(-214)
        .setSignedLong(-14523L);
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 协议字段的长度, 不设置的话,默认自动识别
unsigned boolean true 是否是无符号数
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>;
}



相关文章
|
1月前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
39 3
|
1月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
113 3
|
24天前
|
域名解析 缓存 网络协议
浏览器中输入URL返回页面过程(超级详细)、DNS域名解析服务,TCP三次握手、四次挥手
浏览器中输入URL返回页面过程(超级详细)、DNS域名解析服务,TCP三次握手、四次挥手
|
19天前
|
存储 Java 开发者
Java中的集合框架深入解析
【10月更文挑战第32天】本文旨在为读者揭开Java集合框架的神秘面纱,通过深入浅出的方式介绍其内部结构与运作机制。我们将从集合框架的设计哲学出发,探讨其如何影响我们的编程实践,并配以代码示例,展示如何在真实场景中应用这些知识。无论你是Java新手还是资深开发者,这篇文章都将为你提供新的视角和实用技巧。
18 0
|
1月前
|
Web App开发 IDE 测试技术
自动化测试的利器:Selenium 框架深度解析
【10月更文挑战第2天】在软件开发的海洋中,自动化测试犹如一艘救生艇,让质量保证的过程更加高效与精准。本文将深入探索Selenium这一强大的自动化测试框架,从其架构到实际应用,带领读者领略自动化测试的魅力和力量。通过直观的示例和清晰的步骤,我们将一起学习如何利用Selenium来提升软件测试的效率和覆盖率。
|
1月前
|
人工智能 缓存 Java
深入解析Spring AI框架:在Java应用中实现智能化交互的关键
【10月更文挑战第12天】Spring AI 是 Spring 框架家族的新成员,旨在满足 Java 应用程序对人工智能集成的需求。它支持自然语言处理、图像识别等多种 AI 技术,并提供与云服务(如 OpenAI、Azure Cognitive Services)及本地模型的无缝集成。通过简单的配置和编码,开发者可轻松实现 AI 功能,同时应对模型切换、数据安全及性能优化等挑战。
115 3
http数据包抓包解析
http数据包抓包解析
|
1月前
|
分布式计算 Java 应用服务中间件
NettyIO框架的深度技术解析与实战
【10月更文挑战第13天】Netty是一个异步事件驱动的网络应用程序框架,由JBOSS提供,现已成为Github上的独立项目。
44 0
|
2月前
|
网络协议 网络虚拟化
接收网络包的过程——从硬件网卡解析到IP
【9月更文挑战第18天】这段内容详细描述了网络包接收过程中机制。当网络包触发中断后,内核处理完这批网络包,会进入主动轮询模式,持续处理后续到来的包,直至处理间隙返回其他任务,从而减少中断次数,提高处理效率。此机制涉及网卡驱动初始化时注册轮询函数,通过软中断触发后续处理,并逐步深入内核网络协议栈,最终到达TCP层。整个接收流程分为多个层次,包括DMA技术存入Ring Buffer、中断通知CPU、软中断处理、以及进入内核网络协议栈等多个步骤。
|
2月前
|
前端开发 JavaScript C#
移动应用开发中的跨平台框架解析
【9月更文挑战第5天】在移动应用开发领域,跨平台框架因其“一次编写,处处运行”的便利性而受到开发者的青睐。本文将深入探讨几种流行的跨平台框架,包括React Native、Flutter和Xamarin,并比较它们的优势与局限。我们将通过代码示例揭示这些框架如何简化移动应用的开发过程,同时保持高性能和良好的用户体验。无论你是新手还是有经验的开发者,这篇文章都将成为你了解和选择跨平台框架的宝贵资源。
69 19

推荐镜像

更多
下一篇
无影云桌面