一個便捷的TCP消息包拼裝和解析框架java
簡單經過@Protocol
和@ProtocolField
的配置,便可讓實體對象擁有自動轉化爲TCP傳輸的byte數據和自動byte數據解析。android
支持byte、short、int、long、byte[]、short[]、int[]、long[]、String等經常使用基礎類型,支持類型的拓展git
支持大端和小端兩種存儲方式,支持設置全局默認存儲方式和局部存儲方式。github
支持short、int、long讀取長度的自定義。api
支持對實體字段進行排序,避免解析錯亂。數組
支持自定義協議項和協議解析器。bash
支持自動協議映射,自動根據讀取的opcode識別出對應的協議並進行解析,並根據對應註冊的協議信息判斷協議是否有響應。app
目前支持主流開發工具AndroidStudio的使用,直接配置build.gradle,增長依賴便可.框架
1.先在項目根目錄的 build.gradle 的 repositories 添加:maven
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
。
在Application中註冊協議中心和協議字段中心。
XTCP.getInstance()
.addIProtocolCenter(AppProtocolCenter.getInstance()) //添加協議中心
.addIProtocolFieldCenter(AppProtocolFieldCenter.getInstance(), XTCPProtocolFieldCenter.getInstance()) //添加協議字段中心
.setDefaultStorageMode(StorageMode.BigEndian) //設置默認存儲方式(默認是大端)
.debug(true); //打開調試日誌
複製代碼
經過繼承XProtocolItem
或者實現IProtocolItem
接口,經過@Protocol
和@ProtocolField
註解進行配置。
@Protocol: 用於註解協議項,包括name
、opcode
、resCode
、mode
、desc
等屬性。
@ProtocolField: 用於註解協議項字段,包括index
、isField
、length
、mode
、charset
等屬性。
@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;
}
複製代碼
要想自定義協議項很簡單,一樣的,只須要繼承XProtocolItem
或者實現IProtocolItem
接口,使用@ProtocolField
註解進行配置便可。
【注意】不須要使用@Protocol
進行註解。
public class LoginInfo extends XProtocolItem {
@ProtocolField(index = 0)
private StringField loginName;
@ProtocolField(index = 1)
private StringField password;
}
複製代碼
自定義協議項數組類須要繼承AbstractArrayItem
,詳細的實現案例點擊查看
凡是繼承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());
複製代碼
實現IMessage
接口,可自定義屬於本身的協議消息載體。框架中默認提供了XMessage
和XOrderlyMessage
兩種消息體模版。
1.新建你須要使用的消息體模版。
2.設置你傳輸的協議項。
3.使用msg2Byte
方法將消息轉化爲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());
複製代碼
若是你對協議的解析有特殊的需求,可實現IProtocolParser
接口,並經過XTCP.getInstance().setIProtocolParser
來替換默認的協議解析器。
【注意】謹慎替換,若是替換方法有誤的話,會致使整個框架沒法正常使用,建議不要替換。
屬性名 | 類型 | 默認值 | 備註 |
---|---|---|---|
name | String | "" | 協議的名稱 |
opCode | byte | /(必填) | 協議命令碼,協議命令的惟一號 |
resCode | byte | -1 | 協議響應碼(結果對應的命令碼) |
mode | StorageMode | StorageMode.Default | 數據存儲方式(大端 or 小端) |
desc | String | "" | 描述信息 |
屬性名 | 類型 | 默認值 | 備註 |
---|---|---|---|
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 |
# xtcp
-keep @com.xuexiang.xtcp.annotation.* class * {*;}
-keep class * {
@com.xuexiang.xtcp.annotation.* <fields>;
}
-keepclassmembers class * {
@com.xuexiang.xtcp.annotation.* <methods>;
}
複製代碼