使用AndroidSocketClient庫建立SSL安全連結
AndroidSocketClient
socket client server簡易封裝
Import
Add it in your project`s build.gradle at the end of repositories:
repositories {
// ...
maven { url "https://jitpack.io" }
}
Step 2. Add the dependency in the form
dependencies {
compile `com.github.vilyever:AndroidSocketClient:3.0.3`
}
Updates
-
3.0.3
提升readByLength按長度讀取的速度 issue #26 -
3.0.2
修復初次連線失敗時,因CountDownTimer導致崩潰的問題 issue #24 -
3.0.1
修復包頭驗證bug,by zzdwuliang
增加地址檢測的詳細log -
3.0.0
支援ReadToData和ReadToLength自動讀取以下兩種結構
常見包結構1:【包頭(可選)】【正文】【包尾】
常見包結構2:【包頭(可選)】【餘下包長度(正文加包尾長度)(此部分也可做包頭)(此部分長度固定)】【正文】【包尾(可選)】
Usage
app模組下包含簡單的使用demo
請一定設定讀取策略socketClient.getSocketPacketHelper().setReadStrategy();
遠端端連線資訊配置
socketClient.getAddress().setRemoteIP(IPUtil.getLocalIPAddress(true)); // 遠端端IP地址
socketClient.getAddress().setRemotePort("21998"); // 遠端端埠號
socketClient.getAddress().setConnectionTimeout(15 * 1000); // 連線超時時長,單位毫秒
預設String編碼配置
/**
* 設定自動轉換String型別到byte[]型別的編碼
* 如未設定(預設為null),將不能使用{@link SocketClient#sendString(String)}傳送訊息
* 如設定為非null(如UTF-8),在接受訊息時會自動嘗試在接收執行緒(非主執行緒)將接收的byte[]資料依照編碼轉換為String,在{@link SocketResponsePacket#getMessage()}讀取
*/
socketClient.setCharsetName(CharsetUtil.UTF_8); // 設定編碼為UTF-8
固定心跳包配置
/**
* 設定自動傳送的心跳包資訊
*/
socketClient.getHeartBeatHelper().setDefaultSendData(CharsetUtil.stringToData("HeartBeat", CharsetUtil.UTF_8));
/**
* 設定遠端端傳送到本地的心跳包資訊內容,用於判斷接收到的資料包是否是心跳包
* 通過{@link SocketResponsePacket#isHeartBeat()} 檢視資料包是否是心跳包
*/
socketClient.getHeartBeatHelper().setDefaultReceiveData(CharsetUtil.stringToData("HeartBeat", CharsetUtil.UTF_8));
socketClient.getHeartBeatHelper().setHeartBeatInterval(10 * 1000); // 設定自動傳送心跳包的間隔時長,單位毫秒
socketClient.getHeartBeatHelper().setSendHeartBeatEnabled(true); // 設定允許自動傳送心跳包,此值預設為false
動態變化心跳包配置
/**
* 設定自動傳送的心跳包資訊
* 此資訊動態生成
*
* 每次傳送心跳包時自動呼叫
*/
socketClient.getHeartBeatHelper().setSendDataBuilder(new SocketHeartBeatHelper.SendDataBuilder() {
@Override
public byte[] obtainSendHeartBeatData(SocketHeartBeatHelper helper) {
/**
* 使用當前日期作為心跳包
*/
byte[] heartBeatPrefix = new byte[]{0x1F, 0x1F};
byte[] heartBeatSuffix = new byte[]{0x1F, 0x1F};
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
byte[] heartBeatInfo = CharsetUtil.stringToData(sdf.format(new Date()), CharsetUtil.UTF_8);
byte[] data = new byte[heartBeatPrefix.length + heartBeatSuffix.length + heartBeatInfo.length];
System.arraycopy(heartBeatPrefix, 0, data, 0, heartBeatPrefix.length);
System.arraycopy(heartBeatInfo, 0, data, heartBeatPrefix.length, heartBeatInfo.length);
System.arraycopy(heartBeatSuffix, 0, data, heartBeatPrefix.length + heartBeatInfo.length, heartBeatSuffix.length);
return data;
}
});
/**
* 設定遠端端傳送到本地的心跳包資訊的檢測器,用於判斷接收到的資料包是否是心跳包
* 通過{@link SocketResponsePacket#isHeartBeat()} 檢視資料包是否是心跳包
*/
socketClient.getHeartBeatHelper().setReceiveHeartBeatPacketChecker(new SocketHeartBeatHelper.ReceiveHeartBeatPacketChecker() {
@Override
public boolean isReceiveHeartBeatPacket(SocketHeartBeatHelper helper, SocketResponsePacket packet) {
/**
* 判斷資料包資訊是否含有指定的心跳包字首和字尾
*/
byte[] heartBeatPrefix = new byte[]{0x1F, 0x1F};
byte[] heartBeatSuffix = new byte[]{0x1F, 0x1F};
if (Arrays.equals(heartBeatPrefix, Arrays.copyOfRange(packet.getData(), 0, heartBeatPrefix.length))
&& Arrays.equals(heartBeatSuffix, Arrays.copyOfRange(packet.getData(), packet.getData().length - heartBeatSuffix.length, packet.getData().length))) {
return true;
}
return false;
}
});
socketClient.getHeartBeatHelper().setHeartBeatInterval(10 * 1000); // 設定自動傳送心跳包的間隔時長,單位毫秒
socketClient.getHeartBeatHelper().setSendHeartBeatEnabled(true); // 設定允許自動傳送心跳包,此值預設為false
自動按包尾分割資訊讀取資料的傳送配置
/**
* 根據連線雙方協議設定自動傳送的包尾資料
* 每次傳送資料包(包括心跳包)都會在傳送包內容後自動傳送此包尾
*
* 例:socketClient.sendData(new byte[]{0x01, 0x02})的步驟為
* 1. socketClient向遠端端傳送包頭(如果設定了包頭資訊)
* 2. socketClient向遠端端傳送正文資料{0x01, 0x02}
* 3. socketClient向遠端端傳送包尾
*
* 使用{@link com.vilyever.socketclient.helper.SocketPacketHelper.ReadStrategy.AutoReadToTrailer}必須設定此項
* 用於分隔多條訊息
*/
socketClient.getSocketPacketHelper().setSendTrailerData(new byte[]{0x13, 0x10});
/**
* 根據連線雙方協議設定自動傳送的包頭資料
* 每次傳送資料包(包括心跳包)都會在傳送包內容前自動傳送此包頭
*
* 若無需包頭可刪除此行
*/
socketClient.getSocketPacketHelper().setSendHeaderData(CharsetUtil.stringToData("SocketClient:", CharsetUtil.UTF_8));
/**
* 設定分段傳送資料長度
* 即在傳送指定長度後通過 {@link SocketClientSendingDelegate#onSendingPacketInProgress(SocketClient, SocketPacket, float, int)}回撥當前傳送進度
*
* 若無需進度回撥可刪除此二行,刪除後仍有【傳送開始】【傳送結束】的回撥
*/
socketClient.getSocketPacketHelper().setSendSegmentLength(8); // 設定傳送分段長度,單位byte
socketClient.getSocketPacketHelper().setSendSegmentEnabled(true); // 設定允許使用分段傳送,此值預設為false
/**
* 設定傳送超時時長
* 在傳送每個資料包時,傳送每段資料的最長時間,超過後自動斷開socket連線
* 通過設定分段傳送{@link SocketPacketHelper#setSendSegmentEnabled(boolean)} 可避免傳送大資料包時因超時斷開,
*
* 若無需限制傳送時長可刪除此二行
*/
socketClient.getSocketPacketHelper().setSendTimeout(30 * 1000); // 設定傳送超時時長,單位毫秒
socketClient.getSocketPacketHelper().setSendTimeoutEnabled(true); // 設定允許使用傳送超時時長,此值預設為false
自動按包尾分割資訊讀取資料的接收配置
/**
* 設定讀取策略為自動讀取到指定的包尾
*/
socketClient.getSocketPacketHelper().setReadStrategy(SocketPacketHelper.ReadStrategy.AutoReadToTrailer);
/**
* 根據連線雙方協議設定的包尾資料
* 每次接收資料包(包括心跳包)都會在檢測接收到與包尾資料相同的byte[]時回撥一個資料包
*
* 例:自動接收遠端端所傳送的socketClient.sendData(new byte[]{0x01, 0x02})【{0x01, 0x02}為將要接收的資料】的步驟為
* 1. socketClient接收包頭(如果設定了包頭資訊)(接收方式為一直讀取到與包頭相同的byte[],即可能過濾掉包頭前的多餘資訊)
* 2. socketClient接收正文和包尾(接收方式為一直讀取到與尾相同的byte[])
* 3. socketClient回撥資料包
*
* 使用{@link com.vilyever.socketclient.helper.SocketPacketHelper.ReadStrategy.AutoReadToTrailer}必須設定此項
* 用於分隔多條訊息
*/
socketClient.getSocketPacketHelper().setReceiveTrailerData(new byte[]{0x13, 0x10});
/**
* 根據連線雙方協議設定的包頭資料
* 每次接收資料包(包括心跳包)都會先接收此包頭
*
* 若無需包頭可刪除此行
*/
socketClient.getSocketPacketHelper().setReceiveHeaderData(CharsetUtil.stringToData("SocketClient:", CharsetUtil.UTF_8));
/**
* 設定接收超時時長
* 在指定時長內沒有資料到達本地自動斷開
*
* 若無需限制接收時長可刪除此二行
*/
socketClient.getSocketPacketHelper().setReceiveTimeout(120 * 1000); // 設定接收超時時長,單位毫秒
socketClient.getSocketPacketHelper().setReceiveTimeoutEnabled(true); // 設定允許使用接收超時時長,此值預設為false
自動按包長度資訊讀取的傳送配置
/**
* 設定包長度轉換器
* 即每次傳送資料時,將包頭以外的資料長度轉換為特定的byte[]傳送到遠端端用於解析還需要讀取多少長度的資料
*
* 例:socketClient.sendData(new byte[]{0x01, 0x02})的步驟為
* 1. socketClient向遠端端傳送包頭(如果設定了包頭資訊)
* 2. socketClient要傳送的資料為{0x01, 0x02},長度為2(若設定了包尾,還需加上包尾的位元組長度),通過此轉換器將int型別的2轉換為4位元組的byte[],遠端端也照此演算法將4位元組的byte[]轉換為int值
* 3. socketClient向遠端端傳送轉換後的長度資訊byte[]
* 4. socketClient向遠端端傳送正文資料{0x01, 0x02}
* 5. socketClient向遠端端傳送包尾(如果設定了包尾資訊)
*
* 此轉換器用於第二步
*
* 使用{@link com.vilyever.socketclient.helper.SocketPacketHelper.ReadStrategy.AutoReadByLength}必須設定此項
* 用於分隔多條訊息
*/
socketClient.getSocketPacketHelper().setSendPacketLengthDataConvertor(new SocketPacketHelper.SendPacketLengthDataConvertor() {
@Override
public byte[] obtainSendPacketLengthDataForPacketLength(SocketPacketHelper helper, int packetLength) {
/**
* 簡單將int轉換為byte[]
*/
byte[] data = new byte[4];
data[3] = (byte) (packetLength & 0xFF);
data[2] = (byte) ((packetLength >> 8) & 0xFF);
data[1] = (byte) ((packetLength >> 16) & 0xFF);
data[0] = (byte) ((packetLength >> 24) & 0xFF);
return data;
}
});
/**
* 根據連線雙方協議設定自動傳送的包頭資料
* 每次傳送資料包(包括心跳包)都會在傳送包內容前自動傳送此包頭
*
* 若無需包頭可刪除此行
*/
socketClient.getSocketPacketHelper().setSendHeaderData(CharsetUtil.stringToData("SocketClient:", CharsetUtil.UTF_8));
/**
* 根據連線雙方協議設定自動傳送的包尾資料
* 每次傳送資料包(包括心跳包)都會在傳送包內容後自動傳送此包尾
*
* 若無需包尾可刪除此行
* 注意:
* 使用{@link com.vilyever.socketclient.helper.SocketPacketHelper.ReadStrategy.AutoReadByLength}時不依賴包尾讀取資料
*/
socketClient.getSocketPacketHelper().setSendTrailerData(new byte[]{0x13, 0x10});
/**
* 設定分段傳送資料長度
* 即在傳送指定長度後通過 {@link SocketClientSendingDelegate#onSendingPacketInProgress(SocketClient, SocketPacket, float, int)}回撥當前傳送進度
*
* 若無需進度回撥可刪除此二行,刪除後仍有【傳送開始】【傳送結束】的回撥
*/
socketClient.getSocketPacketHelper().setSendSegmentLength(8); // 設定傳送分段長度,單位byte
socketClient.getSocketPacketHelper().setSendSegmentEnabled(true); // 設定允許使用分段傳送,此值預設為false
/**
* 設定傳送超時時長
* 在傳送每個資料包時,傳送每段資料的最長時間,超過後自動斷開socket連線
* 通過設定分段傳送{@link SocketPacketHelper#setSendSegmentEnabled(boolean)} 可避免傳送大資料包時因超時斷開,
*
* 若無需限制傳送時長可刪除此二行
*/
socketClient.getSocketPacketHelper().setSendTimeout(30 * 1000); // 設定傳送超時時長,單位毫秒
socketClient.getSocketPacketHelper().setSendTimeoutEnabled(true); // 設定允許使用傳送超時時長,此值預設為false
自動按包長度資訊讀取的接收配置
/**
* 設定讀取策略為自動讀取指定長度
*/
socketClient.getSocketPacketHelper().setReadStrategy(SocketPacketHelper.ReadStrategy.AutoReadByLength);
/**
* 設定包長度轉換器
* 即每次接收資料時,將遠端端傳送到本地的長度資訊byte[]轉換為int,然後讀取相應長度的值
*
* 例:自動接收遠端端所傳送的socketClient.sendData(new byte[]{0x01, 0x02})【{0x01, 0x02}為將要接收的資料】的步驟為
* 1. socketClient接收包頭(如果設定了包頭資訊)(接收方式為一直讀取到與包頭相同的byte[],即可能過濾掉包頭前的多餘資訊)
* 2. socketClient接收長度為{@link SocketPacketHelper#getReceivePacketLengthDataLength()}(此處設定為4)的byte[],通過下面設定的轉換器,將byte[]轉換為int值,此int值暫時稱為X
* 3. socketClient接收長度為X的byte[]
* 4. socketClient接收包尾(如果設定了包尾資訊)(接收方式為一直讀取到與包尾相同的byte[],如無意外情況,此處不會讀取到多餘的資訊)
* 5. socketClient回撥資料包
*
* 此轉換器用於第二步
*
* 使用{@link com.vilyever.socketclient.helper.SocketPacketHelper.ReadStrategy.AutoReadByLength}必須設定此項
* 用於分隔多條訊息
*/
socketClient.getSocketPacketHelper().setReceivePacketLengthDataLength(4);
socketClient.getSocketPacketHelper().setReceivePacketDataLengthConvertor(new SocketPacketHelper.ReceivePacketDataLengthConvertor() {
@Override
public int obtainReceivePacketDataLength(SocketPacketHelper helper, byte[] packetLengthData) {
/**
* 簡單將byte[]轉換為int
*/
int length = (packetLengthData[3] & 0xFF) + ((packetLengthData[2] & 0xFF) << 8) + ((packetLengthData[1] & 0xFF) << 16) + ((packetLengthData[0] & 0xFF) << 24);
return length;
}
});
/**
* 根據連線雙方協議設定的包頭資料
* 每次接收資料包(包括心跳包)都會先接收此包頭
*
* 若無需包頭可刪除此行
*/
socketClient.getSocketPacketHelper().setReceiveHeaderData(CharsetUtil.stringToData("SocketClient:", CharsetUtil.UTF_8));
/**
* 根據連線雙方協議設定的包尾資料
*
* 若無需包尾可刪除此行
* 注意:
* 使用{@link com.vilyever.socketclient.helper.SocketPacketHelper.ReadStrategy.AutoReadByLength}時不依賴包尾讀取資料
*/
socketClient.getSocketPacketHelper().setReceiveTrailerData(new byte[]{0x13, 0x10});
/**
* 設定接收超時時長
* 在指定時長內沒有資料到達本地自動斷開
*
* 若無需限制接收時長可刪除此二行
*/
socketClient.getSocketPacketHelper().setReceiveTimeout(120 * 1000); // 設定接收超時時長,單位毫秒
socketClient.getSocketPacketHelper().setReceiveTimeoutEnabled(true); // 設定允許使用接收超時時長,此值預設為false
手動讀取的傳送配置
/**
* 設定分段傳送資料長度
* 即在傳送指定長度後通過 {@link SocketClientSendingDelegate#onSendingPacketInProgress(SocketClient, SocketPacket, float, int)}回撥當前傳送進度
*
* 若無需進度回撥可刪除此二行,刪除後仍有【傳送開始】【傳送結束】的回撥
*/
socketClient.getSocketPacketHelper().setSendSegmentLength(8); // 設定傳送分段長度,單位byte
socketClient.getSocketPacketHelper().setSendSegmentEnabled(true); // 設定允許使用分段傳送,此值預設為false
/**
* 設定傳送超時時長
* 在傳送每個資料包時,傳送每段資料的最長時間,超過後自動斷開socket連線
* 通過設定分段傳送{@link SocketPacketHelper#setSendSegmentEnabled(boolean)} 可避免傳送大資料包時因超時斷開,
*
* 若無需限制傳送時長可刪除此二行
*/
socketClient.getSocketPacketHelper().setSendTimeout(30 * 1000); // 設定傳送超時時長,單位毫秒
socketClient.getSocketPacketHelper().setSendTimeoutEnabled(true); // 設定允許使用傳送超時時長,此值預設為false
手動讀取的接收配置
/**
* 設定讀取策略為手動讀取
* 手動讀取有兩種方法
* 1. {@link SocketClient#readDataToData(byte[], boolean)} )} 讀取到與指定位元組相同的位元組序列後回撥資料包
* 2. {@link SocketClient#readDataToLength(int)} 讀取指定長度的位元組後回撥資料包
*
* 此時SocketPacketHelper中其他讀取相關設定將會無效化
*/
socketClient.getSocketPacketHelper().setReadStrategy(SocketPacketHelper.ReadStrategy.Manually);
常用回撥配置
// 對應removeSocketClientDelegate
socketClient.registerSocketClientDelegate(new SocketClientDelegate() {
/**
* 連線上遠端端時的回撥
*/
@Override
public void onConnected(SocketClient client) {
SocketPacket packet = socketClient.sendData(new byte[]{0x02}); // 傳送訊息
packet = socketClient.sendString("sy hi!"); // 傳送訊息
socketClient.cancelSend(packet); // 取消傳送,若在等待傳送佇列中則從佇列中移除,若正在傳送則無法取消
}
/**
* 與遠端端斷開連線時的回撥
*/
@Override
public void onDisconnected(SocketClient client) {
// 可在此實現自動重連
socketClient.connect();
}
/**
* 接收到資料包時的回撥
*/
@Override
public void onResponse(final SocketClient client, @NonNull SocketResponsePacket responsePacket) {
byte[] data = responsePacket.getData(); // 獲取接收的byte陣列,不為null
String message = responsePacket.getMessage(); // 獲取按預設設定的編碼轉化的String,可能為null
}
});
傳送狀態回撥配置
// 對應removeSocketClientSendingDelegate
socketClient.registerSocketClientSendingDelegate(new SocketClientSendingDelegate() {
/**
* 資料包開始傳送時的回撥
*/
@Override
public void onSendPacketBegin(SocketClient client, SocketPacket packet) {
}
/**
* 資料包取消傳送時的回撥
* 取消傳送回撥有以下情況:
* 1. 手動cancel仍在排隊,還未傳送過的packet
* 2. 斷開連線時,正在傳送的packet和所有在排隊的packet都會被取消
*/
@Override
public void onSendPacketCancel(SocketClient client, SocketPacket packet) {
}
/**
* 資料包傳送的進度回撥
* progress值為[0.0f, 1.0f]
* 通常配合分段傳送使用
* 可用於顯示檔案等大資料的傳送進度
*/
@Override
public void onSendingPacketInProgress(SocketClient client, SocketPacket packet, float progress, int sendedLength) {
}
/**
* 資料包完成傳送時的回撥
*/
@Override
public void onSendPacketEnd(SocketClient client, SocketPacket packet) {
}
});
接收狀態回撥配置
// 對應removeSocketClientReceiveDelegate
socketClient.registerSocketClientReceiveDelegate(new SocketClientReceivingDelegate() {
/**
* 開始接受一個新的資料包時的回撥
*/
@Override
public void onReceivePacketBegin(SocketClient client, SocketResponsePacket packet) {
}
/**
* 完成接受一個新的資料包時的回撥
*/
@Override
public void onReceivePacketEnd(SocketClient client, SocketResponsePacket packet) {
}
/**
* 取消接受一個新的資料包時的回撥
* 在斷開連線時會觸發
*/
@Override
public void onReceivePacketCancel(SocketClient client, SocketResponsePacket packet) {
}
/**
* 接受一個新的資料包的進度回撥
* progress值為[0.0f, 1.0f]
* 僅作用於ReadStrategy為AutoReadByLength的自動讀取
* 因AutoReadByLength可以首先接受到剩下的資料包長度
*/
@Override
public void onReceivingPacketInProgress(SocketClient client, SocketResponsePacket packet, float progress, int receivedLength) {
}
});
License
相關文章
- mysql建立ssl安全連線的配置MySql
- 動態連結庫(DLL)的建立和使用
- 使用wget提示無法建立SSL連線wget
- 安全連線方式ssl(轉)
- centos無法建立ssl連線CentOS
- SSL連線建立過程分析(1)
- oralce資料庫建立dblink連結資料庫
- SSL連線,搭建網路安全道路
- FreeBSD安全連線方式SSL(轉)
- 使用 SSL 加密的 JDBC 連線 SAP HANA 資料庫加密JDBC資料庫
- mysql之使用SSL連線MySql
- LINUX系統中動態連結庫的建立與使用(轉)Linux
- Netty 實現SSL安全連線(wss://)Netty
- 使用pgpool-ii建立PostgreSQL連結池SQL
- 轉-配置openldap使用SSL連線LDA
- Netty5使用自簽證書實現SSL安全連線Netty
- proxool連線池如何使用SSL方式連線?
- wget下載提示:無法建立SSL連線wget
- express入門04 資料庫連線 表結構建立 模型建立Express資料庫模型
- MySQL 使用 SSL 連線(附 Docker 例子)MySqlDocker
- raw.githubusercontent.com 無法建立 SSL 連線Github
- Akka-CQRS(10)- gRPC on SSL/TLS 安全連線RPCTLS
- 【連結 1】與靜態連結庫連結
- 動態連結庫與靜態連結庫
- cmake 連結動態連結庫
- GCC 使用庫檔名進行連結GC
- C++建立連結串列C++
- 建立一個連結到其他資料庫的DBLINK資料庫
- 執行wget命令,出錯:無法建立 SSL 連線。wget
- 關於weget “無法建立SSL連線”的解決方法
- Mongoose使用population建立關係連結例項說明Go
- gcc庫連結GC
- VB使用ADO物件連結資料庫物件資料庫
- 動態連結庫的生成和使用(二)
- 資料庫連線不能建立.資料庫
- nodejs建立全域性連結NodeJS
- 建立ODBC連結表連SQL原始碼示例SQL原始碼
- 使用 ProxySQL 改進 MySQL SSL 的連線效能MySql