摘要:粘包問題在這種字節(jié)流協(xié)議上做應(yīng)用層分包是網(wǎng)絡(luò)編程的基本需求。分包指的是在發(fā)生一個(gè)消息或一幀數(shù)據(jù)時(shí),通過一定的處理,讓接收方能從字節(jié)流中識(shí)別并截取還原出一個(gè)個(gè)消息。
粘包問題
在 TCP 這種字節(jié)流協(xié)議上做應(yīng)用層分包是網(wǎng)絡(luò)編程的基本需求。分包指的是在發(fā)生一個(gè)消息(message)或一幀(frame)數(shù)據(jù)時(shí),通過一定的處理,讓接收方能從字節(jié)流中識(shí)別并截取(還原)出一個(gè)個(gè)消息。因此,“粘包問題”是個(gè)偽命題
短連接分包對(duì)于短連接的 TCP 服務(wù),分包不是一個(gè)問題,只要發(fā)送方主動(dòng)關(guān)閉連接,就表示一個(gè)消息發(fā)送完畢,接收方 read() 返回0,從而知道消息的結(jié)尾
TCP 發(fā)送機(jī)制為了提高 TCP 的傳輸效率,TCP 有一套自己的發(fā)送機(jī)制
TCP 維持一個(gè)變量,它等于最大報(bào)文段長度 MSS。只要緩存中存放的數(shù)據(jù)達(dá)到 MSS 字節(jié)時(shí),就組裝成一個(gè) TCP 報(bào)文段發(fā)送出去
由發(fā)送方的應(yīng)用進(jìn)程指明要求發(fā)送報(bào)文段,即 TCP 支持的推送(push)操作
發(fā)送方的一個(gè)計(jì)時(shí)器期限到了,這時(shí)把當(dāng)前已有的緩存數(shù)據(jù)裝入報(bào)文段(但長度不能超過 MSS)發(fā)送出去
長連接分包對(duì)于長連接的 TCP 服務(wù),分包有四種方法
消息長度固定
使用特殊的字符或字符串作為消息的邊界,例如 HTTP 協(xié)議的 headers 以“rn”為字段的分隔符
在每條消息的頭部加一個(gè)長度字段,這恐怕是最常見的做法
利用消息本身的格式來分包,例如 XML 格式的消息中
假如消息格式非常簡單,“消息”本身是一個(gè)字符串,每條消息有一個(gè)4字節(jié)的頭部,以網(wǎng)絡(luò)序存放字符串的長度。消息直接沒有間隙,字符串也不要求以 "0" 結(jié)尾
發(fā)送兩條消息“hello”和“smartboy”,打包后的字節(jié)流共有21字節(jié)
0x00, 0x00, 0x00, 0x05, "h", "e", "l", "l", "o", 0x00, 0x00, 0x00, 0x08, "s", "m", "a", "r", "t", "b", "o", "y"
假設(shè)數(shù)據(jù)最終都全部到達(dá),數(shù)據(jù)解析邏輯至少能正確處理以下各種數(shù)據(jù)到達(dá)的次序
一個(gè)字節(jié)一個(gè)字節(jié)到達(dá)
數(shù)據(jù)分兩次到達(dá),第一次收到2個(gè)字節(jié),不足消息的長度字段
數(shù)據(jù)分兩次到達(dá),第一次收到4個(gè)字節(jié),剛好夠長度字段,但是沒有 body
數(shù)據(jù)分兩次到達(dá),第一次收到8個(gè)字節(jié),長度完整,但 body 不完整
數(shù)據(jù)分兩次到達(dá),第一次收到9個(gè)字節(jié),長度完整,但 body 也完整
數(shù)據(jù)分兩次到達(dá),第一次收到10個(gè)字節(jié),第一條消息的長度完整、body 也完整,第二條消息長度不完整
請(qǐng)自行移動(dòng)和增加分割點(diǎn),一共有超過 100 萬種可能(221-1)
數(shù)據(jù)一次就全部到達(dá)
《TCP粘包拆包》 原文鏈接:https://blog.maplemark.cn/2019/04/tcp粘包拆包.html?utm=sf
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/31358.html
摘要:長鏈接模式下,使用固定消息頭長度的方式進(jìn)行消息拆包,解決粘包問題。但如果是短連接多個(gè)消息或長鏈接模式下,就可能會(huì)發(fā)生粘包,客戶端不關(guān)閉服務(wù)端無法通過確定消息讀取完畢的問題。這就需要定義協(xié)議和拆包。 tcp 長鏈接模式下,使用固定消息頭長度的方式進(jìn)行消息拆包,解決粘包問題。 固定消息頭協(xié)議 將消息頭的前N個(gè)字節(jié)固定為消息長度位,結(jié)合業(yè)務(wù)場(chǎng)景,2bytes 或 4bytes,讀取消息時(shí)先讀...
摘要:是一個(gè)面向字節(jié)流的協(xié)議,它是性質(zhì)是流式的,所以它并沒有分段。可基于分隔符解決。編解碼的主要目的就是為了可以編碼成字節(jié)流用于在網(wǎng)絡(luò)中傳輸持久化存儲(chǔ)。 showImg(https://segmentfault.com/img/remote/1460000015895049); 前言 記得前段時(shí)間我們生產(chǎn)上的一個(gè)網(wǎng)關(guān)出現(xiàn)了故障。 這個(gè)網(wǎng)關(guān)邏輯非常簡單,就是接收客戶端的請(qǐng)求然后解析報(bào)文最后發(fā)送...
摘要:在中一般來說通過來創(chuàng)建所需要的線程池,如高并發(fā)原理初探后端掘金閱前熱身為了更加形象的說明同步異步阻塞非阻塞,我們以小明去買奶茶為例。 AbstractQueuedSynchronizer 超詳細(xì)原理解析 - 后端 - 掘金今天我們來研究學(xué)習(xí)一下AbstractQueuedSynchronizer類的相關(guān)原理,java.util.concurrent包中很多類都依賴于這個(gè)類所提供的隊(duì)列式...
摘要:在中一般來說通過來創(chuàng)建所需要的線程池,如高并發(fā)原理初探后端掘金閱前熱身為了更加形象的說明同步異步阻塞非阻塞,我們以小明去買奶茶為例。 AbstractQueuedSynchronizer 超詳細(xì)原理解析 - 后端 - 掘金今天我們來研究學(xué)習(xí)一下AbstractQueuedSynchronizer類的相關(guān)原理,java.util.concurrent包中很多類都依賴于這個(gè)類所提供的隊(duì)列式...
摘要:的方法,的默認(rèn)實(shí)現(xiàn)會(huì)判斷是否是類型注意自動(dòng)拆箱,自動(dòng)裝箱問題。適應(yīng)自旋鎖鎖競(jìng)爭是下的,會(huì)經(jīng)過用戶態(tài)到內(nèi)核態(tài)的切換,是比較花時(shí)間的。在中引入了自適應(yīng)的自旋鎖,說明自旋的時(shí)間不固定,要不要自旋變得越來越聰明。 前言 只有光頭才能變強(qiáng) 之前在刷博客的時(shí)候,發(fā)現(xiàn)一些寫得比較好的博客都會(huì)默默收藏起來。最近在查閱補(bǔ)漏,有的知識(shí)點(diǎn)比較重要的,但是在之前的博客中還沒有寫到,于是趁著閑整理一下。 文本的...
閱讀 1629·2023-04-25 16:29
閱讀 954·2021-11-15 11:38
閱讀 2292·2021-09-23 11:45
閱讀 1419·2021-09-22 16:03
閱讀 2538·2019-08-30 15:54
閱讀 1203·2019-08-30 10:53
閱讀 2602·2019-08-29 15:24
閱讀 1101·2019-08-26 12:25