iOS 智能家居 TCP連接 粘包與斷包處理

在tcp連接中 難免會(huì)出現(xiàn)粘包和斷包的現(xiàn)象,這樣我們就無法獲取到正確的信息,所以在開發(fā)過程中我們要對(duì)數(shù)據(jù)粘包和斷包進(jìn)行處理,拿到我們想要的數(shù)據(jù)

數(shù)據(jù)包格式.png

示例:FC 000C 0001 112233445566 01 0010 FF 94
假如這就是我們想要拿到的正確數(shù)據(jù)

LEN0和LEN1是數(shù)據(jù)長度
首先我們要先打拿到整個(gè)數(shù)據(jù)的長度 000C是一個(gè)16進(jìn)制數(shù),轉(zhuǎn)換成十進(jìn)制就是12。
這里的12指的是數(shù)據(jù)本身的長度,不是轉(zhuǎn)換成字符串的長度,字符串的長度是24。
所以內(nèi)容數(shù)據(jù)就是 0001 112233445566 01 0010 FF
最后的94是校驗(yàn)碼

所以我們需要根據(jù)內(nèi)容數(shù)據(jù)的長度12去拿取正確的數(shù)據(jù)

代碼如下

//存儲(chǔ)TCP連接接收的數(shù)據(jù) 用于解決粘包、斷包問題
@property (strong, nonatomic) NSMutableData *readBuf;

在接收到數(shù)據(jù)方法里進(jìn)行處理

FC 000C 0001 112233445566 01 0010 FF 94

//處理粘包與斷包
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    
    _readBuf = [NSMutableData dataWithData:data];
    
//    NSLog(@"直接得到的數(shù)據(jù)%@",_readBuf);
    while (_readBuf.length >= 3) {
        //長度數(shù)據(jù) 000C
        NSData *lengthData = [_readBuf subdataWithRange:NSMakeRange(1, 2)];
        //內(nèi)容長度 12
        NSInteger length = [[self toHexstring:[self dataToString:lengthData]] integerValue];
        //一個(gè)包的完整長度 加上開頭的FC000C和最后的校驗(yàn)碼94
        NSInteger complateDataLength = length + 4;
        if (_readBuf.length >= complateDataLength) {//夠一個(gè)整包長度
            //截取一個(gè)包的長度(解決粘包)
            NSData *complateData = [_readBuf subdataWithRange:NSMakeRange(0, complateDataLength)];
            //處理數(shù)據(jù)
            [self handleTcpResponseData:complateData];
            //從緩存中截掉處理完的數(shù)據(jù),繼續(xù)循環(huán)
            _readBuf = [NSMutableData dataWithData:[_readBuf subdataWithRange:NSMakeRange(complateDataLength, _readBuf.length - complateDataLength)]];
        } else {//如果緩存中的數(shù)據(jù)長度不夠一個(gè)包的長度,則包不完整(處理半包,繼續(xù)讀取)
            [sock readDataWithTimeout:-1 buffer:_readBuf bufferOffset:_readBuf.length tag:0];//繼續(xù)讀取數(shù)據(jù)
            return;
        }
        //緩存中數(shù)據(jù)都處理完了,繼續(xù)讀取新數(shù)據(jù)
        [sock readDataWithTimeout:-1 buffer:_readBuf bufferOffset:_readBuf.length tag:0];//繼續(xù)讀取數(shù)據(jù)
    }
}

handleTcpResponseData方法是自己寫的處理數(shù)據(jù)方法。

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

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

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