思路:使用Netty的ByteBuf進(jìn)行粘包拆包處理。需自定義其屬性,解析處理的協(xié)議格式下圖。代碼如下:
static SerialPortParameter parameter;
static InputStream is = null;
static int length ;
static byte[] data = null;
static byte[] bytesData = null;
static ByteBuf buf = Unpooled.compositeBuffer();//無限制長(zhǎng)度
static ByteBuffer frameBytes = null;
static int bufflenth ;
public static byte[] readData(SerialPort serialPort) {
try {
//獲得串口的輸入流
is = serialPort.getInputStream();
//獲得數(shù)據(jù)長(zhǎng)度
bufflenth = is.available();
if (bufflenth != 0) {//如果緩沖區(qū)無數(shù)據(jù)就不讀取
buf.writeByte(is.read());//每次讀取一個(gè)字節(jié)
//判斷是否滿足字節(jié)最小數(shù)目,不滿足直接return等待數(shù)據(jù)到來
if (buf.readableBytes() < ProtocolConstant.FRAME_SIZE_MIN) {
return null;
}
int beginReader;//記錄包頭標(biāo)志
while (true) {
// 獲取包頭開始的index
beginReader = buf.readerIndex();
// 標(biāo)記包頭開始的index
buf.markReaderIndex();
// 讀到了協(xié)議的開始標(biāo)志,結(jié)束while循環(huán)
if (buf.readByte() == ProtocolConstant.FRAME_HEAD_FLAG) {
//跳過VendorID 和 DEV_ID
buf.readBytes(10);
//讀取CMD加Payload長(zhǎng)度
byte[] lengthBytes1 = new byte[2];
lengthBytes1[1] = buf.readByte();
lengthBytes1[0] = buf.readByte();
length = FrameCommUtil.bytes2Int(lengthBytes1, 0, lengthBytes1.length);//讀取長(zhǎng)度
//如果長(zhǎng)度符合完整報(bào)文長(zhǎng)度繼續(xù)執(zhí)行。
if(buf.readableBytes() == length + 2){
//跳過數(shù)據(jù)區(qū)
buf.readBytes(length);
//跳過校驗(yàn)和
buf.readByte();
//還原到包頭位置
buf.resetReaderIndex();
//讀取包頭標(biāo)志,因?yàn)槟J(rèn)包頭已經(jīng)讀過
// buf.readByte();
break;
}else{
buf.resetReaderIndex();
return null;
}
}
// 未讀到包頭,略過一個(gè)字節(jié)
// 每次略過,一個(gè)字節(jié),去讀取,包頭信息的開始標(biāo)記
buf.resetReaderIndex();
buf.readByte();
// 當(dāng)略過,一個(gè)字節(jié)之后,
// 數(shù)據(jù)包的長(zhǎng)度,又變得不滿足
// 此時(shí),應(yīng)該結(jié)束。等待后面的數(shù)據(jù)到達(dá)
if (buf.readableBytes() < ProtocolConstant.FRAME_SIZE_MIN) {
return null;
}
}
if (buf.readableBytes() < length + ProtocolConstant.FRAME_SIZE_MIN) {
buf.readerIndex(beginReader);
return null;
}
buf.resetReaderIndex();
//創(chuàng)造一個(gè)長(zhǎng)度為length的容納數(shù)據(jù)的數(shù)組
data = new byte[length + ProtocolConstant.FRAME_SIZE_MIN];
try {
buf.readBytes(data);//將數(shù)據(jù)寫入數(shù)組
frameBytes = ByteBuffer.allocate(15 + length);
frameBytes.put(data);//放入數(shù)據(jù)
bytesData = frameBytes.array();//轉(zhuǎn)換為數(shù)組
} catch (Exception e) {
e.printStackTrace();
return null;
}
return bytesData;//返回完整報(bào)文
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
數(shù)據(jù)格式
image.png