串口數(shù)據(jù)拆包問題處理

思路:使用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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容