日韩美女乱婬AAA高清视频_国产色爱AV资源综合区_国产女同性黄网在线观看_欧美日韩一卡2卡3卡4卡新区乱码_俺来也俺也啪www色_精品久久久久久综合日本_99国内偷揿国产精品人妻_国产蜜芽剧果冻传媒_日本特级aaaaaaaa片_国产偷人妻精品一区二区在线

簡體中文

RDT的切包和組包

RDT可靠傳輸模塊 | TUTK P2P SDK 開發(fā)手冊

一、概述

RDT(Reliable Data Transfer)是 TUTK P2P SDK 中的可靠傳輸模塊,提供通用的 RDT_ReadRDT_Write 數(shù)據(jù)傳輸接口,適用于需要穩(wěn)定傳輸數(shù)據(jù)的場景(如設(shè)備控制指令、文件傳輸?shù)龋?/p>

核心特性說明:

  • 發(fā)送端/接收端均內(nèi)置緩沖區(qū),緩存?zhèn)鬏斨谢虼幚淼臄?shù)據(jù);
  • 傳輸機制:數(shù)據(jù)不會嚴格按"一幀一幀"傳輸,可能存在「單幀分片」或「多幀合并」的情況;
  • 關(guān)鍵要求:接收端必須通過自定義幀格式解析數(shù)據(jù),實現(xiàn)分片重組,才能獲取完整的業(yè)務數(shù)據(jù)。

二、RDT幀設(shè)計

為實現(xiàn)數(shù)據(jù)分片重組,需自定義統(tǒng)一的幀格式,確保發(fā)送端和接收端遵循相同的解析規(guī)則。推薦幀結(jié)構(gòu)分為5個部分,兼顧完整性校驗和擴展性:

(一)參考幀結(jié)構(gòu)
// 幀結(jié)構(gòu)總覽(字節(jié)數(shù)固定部分+可變部分) frmBegin[4] | frmInfo[5] | data[dataSize] | frmEnd[2] // 各部分說明 1. frmBegin[4]:幀起始標志(固定4字節(jié))  - 作用:標識一幀數(shù)據(jù)的開始,用于同步幀邊界  - 示例:0xAA 0xBB 0xCC 0xDD(可自定義,需兩端一致) 2. frmInfo[5]:幀信息頭(固定5字節(jié),含業(yè)務核心信息)  - 子結(jié)構(gòu):type[1] + dataSize[4]    - type[1]:數(shù)據(jù)類型(1字節(jié),自定義業(yè)務類型,如0x01=控制指令、0x02=文件數(shù)據(jù))    - dataSize[4]:數(shù)據(jù)體長度(4字節(jié),大端/小端需兩端統(tǒng)一,推薦大端) 3. data[dataSize]:業(yè)務數(shù)據(jù)體(可變長度,由dataSize指定)  - 存儲實際需要傳輸?shù)臉I(yè)務數(shù)據(jù)(如指令內(nèi)容、文件分片等) 4. frmEnd[2]:幀結(jié)束標志(固定2字節(jié))  - 作用:標識一幀數(shù)據(jù)的結(jié)束,用于校驗幀完整性  - 示例:0xEE 0xFF(可自定義,需兩端一致)
說明:幀結(jié)構(gòu)的固定部分(frmBegin、frmInfo、frmEnd)總長度為11字節(jié)(也可根據(jù)實際場景自行擴展),可變部分長度由dataSize動態(tài)指定,確保解析時可準確定位各字段邊界。
(二)幀結(jié)構(gòu)自定義說明
  • 核心約束:frmBegin、frmInfofrmEnd 的長度和格式需在發(fā)送端、接收端完全一致,否則會導致解析失?。?/li>
  • 擴展建議:若需更多業(yè)務字段(如校驗碼、序列號),可擴展 frmInfo 長度(如改為8字節(jié)),示例:                        
    frmInfo[8] = type[1] + seq[2] + dataSize[4] + crc[1](seq=序列號,crc=數(shù)據(jù)校驗碼);
  • 注意:幀標志(frmBegin/frmEnd)需避免與業(yè)務數(shù)據(jù)重復,防止誤識別幀邊界。

三、幀讀取方法

接收端需按「幀起始標志 → 幀信息頭 → 業(yè)務數(shù)據(jù) → 幀結(jié)束標志」的順序讀取數(shù)據(jù),通過循環(huán)重試機制處理分片傳輸場景,確保獲取完整幀。

以下為各環(huán)節(jié)的標準實現(xiàn)(C語言示例),依賴 RDT 核心接口 RDT_Read(rdt_channel_id, buf, len, timeout)。

1. 讀取幀起始標志(frmBegin)

讀取固定4字節(jié)的幀起始標志,用于定位幀的開始位置。

// 全局變量:RDT通道ID(需在建立RDT連接后獲取,如IOTC_Connect_RDT返回的通道ID) int rdt_channel_id = -1; // 幀起始標志定義(需與發(fā)送端一致) #define FRAME_BEGIN_SIZE 4 const unsigned char FRAME_BEGIN[] = {0xAA, 0xBB, 0xCC, 0xDD}; /** * 讀取幀起始標志 * @return 0=讀取成功且標志匹配,負數(shù)=錯誤碼(-1=緩沖區(qū)不足,-2=標志不匹配,其他=RDT_Read錯誤碼) */ int readFrameBegin() {    int readSize = 0;        // 單次讀取字節(jié)數(shù)    int rest = FRAME_BEGIN_SIZE; // 剩余需讀取的字節(jié)數(shù)    unsigned char buffer[FRAME_BEGIN_SIZE] = {0}; // 接收緩沖區(qū)    // 循環(huán)讀取完整的起始標志(處理分片)    while (rest > 0) {        readSize = RDT_Read(            rdt_channel_id,            buffer + (FRAME_BEGIN_SIZE - rest), // 當前寫入位置            rest,            1000 // 超時時間(ms),可根據(jù)業(yè)務調(diào)整        );        // 處理讀取結(jié)果        if (readSize == RDT_ER_TIMEOUT) {            // 超時:繼續(xù)重試(避免因分片傳輸導致讀取失敗)            continue;        } else if (readSize < 0) {            // 非超時錯誤(如通道關(guān)閉):返回RDT錯誤碼            return readSize;        }        rest -= readSize;    }    // 驗證起始標志是否匹配(防止誤識別)    if (memcmp(buffer, FRAME_BEGIN, FRAME_BEGIN_SIZE) != 0) {        return -2; // 標志不匹配,返回自定義錯誤碼    }    return 0; // 讀取成功且標志有效 }
2. 讀取幀信息頭(frmInfo)

讀取固定5字節(jié)的幀信息頭,解析出數(shù)據(jù)類型(type)和數(shù)據(jù)體長度(dataSize),為后續(xù)數(shù)據(jù)讀取做準備。

// 幀信息頭固定大?。?字節(jié)) #define FRAME_INFO_SIZE 5 /** * 讀取幀信息頭 * @param frmInfo 接收幀信息的緩沖區(qū)(需提前分配至少FRAME_INFO_SIZE字節(jié)) * @param frmInfoBufferSize 緩沖區(qū)實際大?。ㄓ糜诤戏ㄐ孕r灒? * @return 0=讀取成功,負數(shù)=錯誤碼(-1=參數(shù)非法,其他=RDT_Read錯誤碼) */ int readFrameInfo(char* frmInfo, size_t frmInfoBufferSize) {    // 參數(shù)合法性校驗(避免空指針和緩沖區(qū)溢出)    if (frmInfo == NULL || frmInfoBufferSize < FRAME_INFO_SIZE) {        return -1;    }    int readSize = 0;    int rest = FRAME_INFO_SIZE;    memset(frmInfo, 0, frmInfoBufferSize); // 清空緩沖區(qū)    // 循環(huán)讀取完整的幀信息頭    while (rest > 0) {        readSize = RDT_Read(            rdt_channel_id,            frmInfo + (FRAME_INFO_SIZE - rest),            rest,            1000        );        if (readSize == RDT_ER_TIMEOUT) {            continue;        } else if (readSize < 0) {            return readSize;        }        rest -= readSize;    }    return 0; }
3. 解析幀信息頭(parseFrameInfo)

從讀取到的 frmInfo 中解析出 type(數(shù)據(jù)類型)和 dataSize(數(shù)據(jù)體長度),需注意字節(jié)序轉(zhuǎn)換(若為大端傳輸)。

#include// 用于ntohl函數(shù)(網(wǎng)絡字節(jié)序轉(zhuǎn)主機字節(jié)序) /** * 解析幀信息頭 * @param frmInfo 已讀取的幀信息頭緩沖區(qū)(長度>=FRAME_INFO_SIZE) * @param outType 輸出參數(shù):數(shù)據(jù)類型(需提前分配內(nèi)存) * @param outDataSize 輸出參數(shù):數(shù)據(jù)體長度(需提前分配內(nèi)存) * @return 0=解析成功,-1=參數(shù)非法 */ int parseFrameInfo(const char* frmInfo, int* outType, int* outDataSize) {    if (frmInfo == NULL || outType == NULL || outDataSize == NULL) {        return -1;    }    // 解析數(shù)據(jù)類型(1字節(jié),直接讀?。?    *outType = (unsigned char)frmInfo[0];    // 解析數(shù)據(jù)體長度(4字節(jié),假設(shè)發(fā)送端為網(wǎng)絡字節(jié)序,轉(zhuǎn)換為主機字節(jié)序)    uint32_t dataSizeNet = 0;    memcpy(&dataSizeNet, frmInfo + 1, 4); // frmInfo[1]~frmInfo[4]為dataSize    *outDataSize = ntohl(dataSizeNet); // 大端轉(zhuǎn)主機字節(jié)序(若為小端則用ntohs/直接讀取)    return 0; }
4. 讀取業(yè)務數(shù)據(jù)體(data)

根據(jù)解析出的 dataSize 讀取完整的業(yè)務數(shù)據(jù),確保緩沖區(qū)大小足夠容納數(shù)據(jù)體。

/** * 讀取業(yè)務數(shù)據(jù)體 * @param dataBuf 接收數(shù)據(jù)的緩沖區(qū)(需提前分配>=dataSize字節(jié)) * @param dataBufSize 緩沖區(qū)實際大小(用于合法性校驗) * @param dataSize 預期讀取的數(shù)據(jù)體長度(從frmInfo解析獲得) * @return 實際讀取的字節(jié)數(shù)(正常=dataSize),負數(shù)=錯誤碼(-1=參數(shù)非法,其他=RDT_Read錯誤碼) */ int readOneFrameData(char* dataBuf, size_t dataBufSize, int dataSize) {    // 參數(shù)合法性校驗(防止緩沖區(qū)溢出和非法參數(shù))    if (dataBuf == NULL || dataBufSize < (size_t)dataSize || dataSize <= 0) {        readSize = RDT_Read(            rdt_channel_id,            dataBuf + (dataSize - rest), // 當前寫入位置            rest,            1000        );        if (readSize == RDT_ER_TIMEOUT) {            continue;        } else if (readSize < 0) {            return readSize;        }        totalRead += readSize;        rest -= readSize;    }    return totalRead; }
5. 讀取幀結(jié)束標志(frmEnd)

讀取固定2字節(jié)的幀結(jié)束標志,驗證幀的完整性。

// 幀結(jié)束標志定義(需與發(fā)送端一致) #define FRAME_END_SIZE 2 const unsigned char FRAME_END[] = {0xEE, 0xFF}; /** * 讀取幀結(jié)束標志 * @return 0=讀取成功且標志匹配,負數(shù)=錯誤碼(-2=標志不匹配,其他=RDT_Read錯誤碼) */ int readFrameEnd() {    int readSize = 0;    int rest = FRAME_END_SIZE;    unsigned char buffer[FRAME_END_SIZE] = {0};    // 循環(huán)讀取完整的結(jié)束標志    while (rest > 0) {        readSize = RDT_Read(            rdt_channel_id,            buffer + (FRAME_END_SIZE - rest),            rest,            1000        );        if (readSize == RDT_ER_TIMEOUT) {            continue;        } else if (readSize < 0) {            return readSize;        }        rest -= readSize;    }    // 驗證結(jié)束標志是否匹配    if (memcmp(buffer, FRAME_END, FRAME_END_SIZE) != 0) {        return -2;    }    return 0; }

四、完整讀取示例

將上述分步讀取方法整合,實現(xiàn)持續(xù)監(jiān)聽并解析RDT數(shù)據(jù)幀的完整流程,包含錯誤處理和異常兼容。

// 業(yè)務數(shù)據(jù)緩沖區(qū)大小(根據(jù)實際最大dataSize調(diào)整,示例:100KB) #define MAX_DATA_BUFFER_SIZE 100 * 1024 // 業(yè)務數(shù)據(jù)處理函數(shù)(示例:根據(jù)數(shù)據(jù)類型分發(fā)處理) void handleBusinessData(int dataType, const char* dataBuf, int dataSize) {    switch (dataType) {        case 0x01: // 控制指令類型            printf("收到控制指令,長度:%d字節(jié),內(nèi)容:%s\n", dataSize, dataBuf);            // TODO:執(zhí)行控制指令邏輯            break;        case 0x02: // 文件數(shù)據(jù)類型            printf("收到文件數(shù)據(jù),長度:%d字節(jié)\n", dataSize);            // TODO:寫入文件或拼接文件分片            break;        default:            printf("收到未知類型數(shù)據(jù),類型:%d,長度:%d字節(jié)\n", dataType, dataSize);            break;    } } // 主循環(huán):持續(xù)讀取并解析RDT數(shù)據(jù)幀 int rdtFrameReadLoop() {    char frmInfo[FRAME_INFO_SIZE] = {0};    char dataBuffer[MAX_DATA_BUFFER_SIZE] = {0};    int dataType = 0;    int dataSize = 0;    int ret = 0;    // 循環(huán)監(jiān)聽數(shù)據(jù)(直到通道關(guān)閉或主動退出)    while (1) {        // 1. 讀取幀起始標志        ret = readFrameBegin();        if (ret < 0) {            if (ret == -2) {                printf("幀起始標志不匹配,跳過異常數(shù)據(jù)\n");                continue; // 標志不匹配,跳過當前數(shù)據(jù),繼續(xù)下一輪監(jiān)聽            } else {                printf("讀取幀起始標志失敗,錯誤碼:%d\n", ret);                break; // RDT通道錯誤,退出循環(huán)            }        }        // 2. 讀取幀信息頭        ret = readFrameInfo(frmInfo, sizeof(frmInfo));        if (ret < 0) {            printf("讀取幀信息頭失敗,錯誤碼:%d\n", ret);            break;        }        // 3. 解析幀信息頭        ret = parseFrameInfo(frmInfo, &dataType, &dataSize);        if (ret < 0) {            printf("解析幀信息頭失敗\n");            continue;        }        // 4. 校驗數(shù)據(jù)大小合法性(防止緩沖區(qū)溢出)        if (dataSize <= 0="" datasize=""> MAX_DATA_BUFFER_SIZE) {            printf("無效的數(shù)據(jù)大?。?d字節(jié)(超出緩沖區(qū)限制),跳過當前幀\n", dataSize);            // 跳過當前幀的剩余數(shù)據(jù)(避免影響后續(xù)幀解析)            // TODO:可選實現(xiàn):讀取并丟棄當前幀的data和frmEnd            continue;        }        // 5. 讀取業(yè)務數(shù)據(jù)體        ret = readOneFrameData(dataBuffer, sizeof(dataBuffer), dataSize);        if (ret < 0) {            printf("讀取業(yè)務數(shù)據(jù)失敗,錯誤碼:%d\n", ret);            break;        }        if (ret != dataSize) {            printf("數(shù)據(jù)體不完整(預期:%d字節(jié),實際:%d字節(jié)),跳過當前幀\n", dataSize, ret);            continue;        }        // 6. 讀取幀結(jié)束標志        ret = readFrameEnd();        if (ret < 0) {            if (ret == -2) {                printf("幀結(jié)束標志不匹配,跳過當前幀\n");                continue;            } else {                printf("讀取幀結(jié)束標志失敗,錯誤碼:%d\n", ret);                break;            }        }        // 7. 處理完整的業(yè)務數(shù)據(jù)        handleBusinessData(dataType, dataBuffer, dataSize);        // 清空緩沖區(qū)(避免殘留數(shù)據(jù)影響下一輪解析)        memset(dataBuffer, 0, sizeof(dataBuffer));    }    printf("RDT幀讀取循環(huán)退出\n");    return ret; }

即刻開啟您的物聯(lián)網(wǎng)之旅

聯(lián)系解決方案專家
Kalay App
資訊安全白皮書
全球?qū)@季?/a>
解決方案
新聞動態(tài)
公司動態(tài)
行業(yè)資訊
媒體報道
永續(xù)發(fā)展
經(jīng)營者的話
社會參與
環(huán)境永續(xù)
公司治理

+86 755 27702549

7×24小時服務熱線

法律聲明 隱私權(quán)條款

關(guān)注“TUTK”

TUTK服務盡在掌握

? 2022 物聯(lián)智慧科技(深圳)有限公司版權(quán)所有粵ICP備14023641號
在線咨詢
掃一掃

TUTK服務盡在掌握

全國免費服務熱線
+86 755 27702549

返回頂部