Socket粘包,拆包處理

在iOS中用socket做即時(shí)通訊時(shí)蛇券,經(jīng)常會(huì)遇到粘包的問題缀壤。

什么是粘包?

粘包:socket傳輸數(shù)據(jù)是由多個(gè)連續(xù)的數(shù)據(jù)包組成纠亚,他們被連續(xù)的存儲(chǔ)在緩存中塘慕,在讀取數(shù)據(jù)包時(shí)可能由于某些原因?qū)е芦@取到了錯(cuò)誤的發(fā)送邊界,這時(shí)后就會(huì)出現(xiàn)后一個(gè)數(shù)據(jù)包的頭連接在了前一個(gè)數(shù)據(jù)包的尾部蒂胞。

怎么解決粘包图呢?

因?yàn)門CP協(xié)議是基于字節(jié)流的,所以在應(yīng)用層就要自己解決數(shù)據(jù)的邊界問題骗随。
一般來說岳瞭,定義數(shù)據(jù)有兩種方式,定義長度 或者 定義一個(gè)終結(jié)符蚊锹。
下面通過項(xiàng)目中的代碼來解釋怎么解決粘包瞳筏。

func didReadData(_ data:Data){
        //接收的數(shù)據(jù)先寫入緩存
        cache += [UInt8](data)
        while cache.count>8 {
            print("讀取到數(shù)據(jù),開始解析牡昆,剩余數(shù)據(jù)長度:\(cache.count)")
            //0-4位存儲(chǔ)消息類型
            let typeBytes = cache[0..<4]
            //4-8位存儲(chǔ)數(shù)據(jù)包長度
            let lengthBytes = cache[4..<8]
            let typeData = Data(typeBytes)
            let lengthData = Data(lengthBytes)
            //注意大小端轉(zhuǎn)換問題
            let type = Int32(bigEndian: typeData.withUnsafeBytes { $0.baseAddress!.bindMemory(to: Int32.self, capacity: 4).pointee })
            let length = Int32(bigEndian: lengthData.withUnsafeBytes { $0.baseAddress!.bindMemory(to: Int32.self, capacity: 4).pointee })
            //數(shù)據(jù)包長度不夠姚炕,跳出循環(huán)摊欠,繼續(xù)讀取笑一個(gè)包
            if cache.count < 8+Int(length){
                break
            }
            //獲取到完整的數(shù)據(jù)包
            let resultBytes = cache[8..<8+Int(length)]
            let resultData = Data(resultBytes)
            //將數(shù)據(jù)傳給delegate進(jìn)行處理
            self.delegate?.socketDidRead(type: type, data: resultData,retry:true)
            //沾包循環(huán)讀取
            let begin = 8+Int(length)
            let end = cache.count
            cache = Array(cache[begin..<end])
        }
        sendSocket?.readData(withTimeout: -1, tag: 0)
    }

主要流程如下
1、將接收的數(shù)據(jù)保存到緩存數(shù)據(jù)中柱宦。
2些椒、while循環(huán)去讀數(shù)據(jù),直到判斷緩存是否小于8掸刊。(0-4字節(jié)為消息類型免糕,4-8為消息長度)
3、循環(huán)中去判斷緩存數(shù)據(jù)是否大于內(nèi)容的長度忧侧,如果大于石窑,則解析掉這條數(shù)據(jù),并從緩存中刪除蚓炬,如果緩存數(shù)據(jù)還有大于8字節(jié)長度的數(shù)據(jù)松逊,則循環(huán)讀取數(shù)據(jù)。
如果數(shù)據(jù)長度小于獲取到的內(nèi)容長度肯夏,則說明出現(xiàn)粘包经宏,則繼續(xù)readData,繼續(xù)拼接緩存數(shù)據(jù)驯击。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末烁兰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子徊都,更是在濱河造成了極大的恐慌沪斟,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碟贾,死亡現(xiàn)場離奇詭異币喧,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)袱耽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門杀餐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人朱巨,你說我怎么就攤上這事史翘。” “怎么了冀续?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵琼讽,是天一觀的道長。 經(jīng)常有香客問我洪唐,道長钻蹬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任凭需,我火速辦了婚禮问欠,結(jié)果婚禮上肝匆,老公的妹妹穿的比我還像新娘。我一直安慰自己顺献,他們只是感情好旗国,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著注整,像睡著了一般能曾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肿轨,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天寿冕,我揣著相機(jī)與錄音,去河邊找鬼萝招。 笑死蚂斤,一個(gè)胖子當(dāng)著我的面吹牛存捺,可吹牛的內(nèi)容都是我干的槐沼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼捌治,長吁一口氣:“原來是場噩夢啊……” “哼岗钩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起肖油,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤兼吓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后森枪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體视搏,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年县袱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了浑娜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡式散,死狀恐怖筋遭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情暴拄,我是刑警寧澤漓滔,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站乖篷,受9級特大地震影響响驴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜撕蔼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一豁鲤、第九天 我趴在偏房一處隱蔽的房頂上張望石蔗。 院中可真熱鬧,春花似錦畅形、人聲如沸养距。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棍厌。三九已至,卻和暖如春竖席,著一層夾襖步出監(jiān)牢的瞬間耘纱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工毕荐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留束析,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓憎亚,卻偏偏與公主長得像员寇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子第美,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容