<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試題:聊聊TCP的粘包、拆包以及解決方案

          共 1975字,需瀏覽 4分鐘

           ·

          2021-03-11 13:22

          TCP的粘包和拆包問(wèn)題往往出現(xiàn)在基于TCP協(xié)議的通訊中,比如RPC框架、Netty等。如果你的簡(jiǎn)歷中寫(xiě)了類(lèi)似的技術(shù)或者你所面試的公司使用了相關(guān)的技術(shù),被問(wèn)到該面試的幾率會(huì)非常高。

          今天這篇文章就帶大家詳細(xì)了解一下TCP的粘包和拆包以及解決方案。

          什么是粘包?

          在學(xué)習(xí)粘包之前,先糾正一下讀音,很多視頻教程中將“粘”讀作“nián”。經(jīng)過(guò)調(diào)研,個(gè)人更傾向于讀“zhān bāo”。

          如果在百度百科上搜索“粘包”,對(duì)應(yīng)的讀音便是“zhān bāo”,語(yǔ)義解釋為:網(wǎng)絡(luò)技術(shù)術(shù)語(yǔ)。指TCP協(xié)議中,發(fā)送方發(fā)送的若干包數(shù)據(jù)到接收方接收時(shí)粘成一包,從接收緩沖區(qū)看,后一包數(shù)據(jù)的頭緊接著前一包數(shù)據(jù)的尾。

          TCP是面向字節(jié)流的協(xié)議,就是沒(méi)有界限的一串?dāng)?shù)據(jù),本沒(méi)有“包”的概念,“粘包”和“拆包”一說(shuō)是為了有助于形象地理解這兩種現(xiàn)象。

          為什么UDP沒(méi)有粘包?

          粘包拆包問(wèn)題在數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層以及傳輸層都有可能發(fā)生。日常的網(wǎng)絡(luò)應(yīng)用開(kāi)發(fā)大都在傳輸層進(jìn)行,由于UDP有消息保護(hù)邊界,不會(huì)發(fā)生粘包拆包問(wèn)題,因此粘包拆包問(wèn)題只發(fā)生在TCP協(xié)議中。

          粘包拆包發(fā)生場(chǎng)景

          因?yàn)門(mén)CP是面向流,沒(méi)有邊界,而操作系統(tǒng)在發(fā)送TCP數(shù)據(jù)時(shí),會(huì)通過(guò)緩沖區(qū)來(lái)進(jìn)行優(yōu)化,例如緩沖區(qū)為1024個(gè)字節(jié)大小。

          如果一次請(qǐng)求發(fā)送的數(shù)據(jù)量比較小,沒(méi)達(dá)到緩沖區(qū)大小,TCP則會(huì)將多個(gè)請(qǐng)求合并為同一個(gè)請(qǐng)求進(jìn)行發(fā)送,這就形成了粘包問(wèn)題。

          如果一次請(qǐng)求發(fā)送的數(shù)據(jù)量比較大,超過(guò)了緩沖區(qū)大小,TCP就會(huì)將其拆分為多次發(fā)送,這就是拆包。

          關(guān)于粘包和拆包可以參考下圖的幾種情況:


          粘包/拆包

          上圖中演示了以下幾種情況:

          • 正常的理想情況,兩個(gè)包恰好滿(mǎn)足TCP緩沖區(qū)的大小或達(dá)到TCP等待時(shí)長(zhǎng),分別發(fā)送兩個(gè)包;
          • 粘包:兩個(gè)包較小,間隔時(shí)間短,發(fā)生粘包,合并成一個(gè)包發(fā)送;
          • 拆包:一個(gè)包過(guò)大,超過(guò)緩存區(qū)大小,拆分成兩個(gè)或多個(gè)包發(fā)送;
          • 拆包和粘包:Packet1過(guò)大,進(jìn)行了拆包處理,而拆出去的一部分又與Packet2進(jìn)行粘包處理。

          常見(jiàn)的解決方案

          對(duì)于粘包和拆包問(wèn)題,常見(jiàn)的解決方案有四種:

          • 發(fā)送端將每個(gè)包都封裝成固定的長(zhǎng)度,比如100字節(jié)大小。如果不足100字節(jié)可通過(guò)補(bǔ)0或空等進(jìn)行填充到指定長(zhǎng)度;
          • 發(fā)送端在每個(gè)包的末尾使用固定的分隔符,例如\r\n。如果發(fā)生拆包需等待多個(gè)包發(fā)送過(guò)來(lái)之后再找到其中的\r\n進(jìn)行合并;例如,F(xiàn)TP協(xié)議;
          • 將消息分為頭部和消息體,頭部中保存整個(gè)消息的長(zhǎng)度,只有讀取到足夠長(zhǎng)度的消息之后才算是讀到了一個(gè)完整的消息;
          • 通過(guò)自定義協(xié)議進(jìn)行粘包和拆包的處理。

          Netty對(duì)粘包和拆包問(wèn)題的處理

          Netty對(duì)解決粘包和拆包的方案做了抽象,提供了一些解碼器(Decoder)來(lái)解決粘包和拆包的問(wèn)題。如:

          • LineBasedFrameDecoder:以行為單位進(jìn)行數(shù)據(jù)包的解碼;
          • DelimiterBasedFrameDecoder:以特殊的符號(hào)作為分隔來(lái)進(jìn)行數(shù)據(jù)包的解碼;
          • FixedLengthFrameDecoder:以固定長(zhǎng)度進(jìn)行數(shù)據(jù)包的解碼;
          • LenghtFieldBasedFrameDecode:適用于消息頭包含消息長(zhǎng)度的協(xié)議(最常用);

          基于Netty進(jìn)行網(wǎng)絡(luò)讀寫(xiě)的程序,可以直接使用這些Decoder來(lái)完成數(shù)據(jù)包的解碼。對(duì)于高并發(fā)、大流量的系統(tǒng)來(lái)說(shuō),每個(gè)數(shù)據(jù)包都不應(yīng)該傳輸多余的數(shù)據(jù)(所以補(bǔ)齊的方式不可取),LenghtFieldBasedFrameDecode更適合這樣的場(chǎng)景。

          小結(jié)

          TCP協(xié)議粘包拆包問(wèn)題是因?yàn)門(mén)CP協(xié)議數(shù)據(jù)傳輸是基于字節(jié)流的,它不包含消息、數(shù)據(jù)包等概念,需要應(yīng)用層協(xié)議自己設(shè)計(jì)消息的邊界,即消息幀(Message Framing)。如果應(yīng)用層協(xié)議沒(méi)有使用基于長(zhǎng)度或者基于終結(jié)符息邊界等方式進(jìn)行處理,則會(huì)導(dǎo)致多個(gè)消息的粘包和拆包。

          雖然很多框架中都有現(xiàn)成的解決方案,比如Netty,但底層的原理我們還是要清楚的,而且還要知道有這么事,才能更好的結(jié)合場(chǎng)景進(jìn)行使用。

          往期推薦

          JDK9對(duì)String字符串的新一輪優(yōu)化,不可不知

          再一次實(shí)戰(zhàn)策略模式,真是太好用了

          Java自動(dòng)拆箱空指針異常,救火隊(duì)員上線(xiàn)

          還不懂Java的泛型?只用這一篇文章,保證你面試對(duì)答如流

          放棄FastJson!一篇就夠,Jackson的功能原來(lái)如此之牛(萬(wàn)字干貨)



          如果你覺(jué)得這篇文章不錯(cuò),那么,下篇通常會(huì)更好。添加微信好友,可備注“加群”(微信號(hào):zhuan2quan)

          一篇文章就看透技術(shù)本質(zhì)的人,
            和花一輩子都看不清的人,
            注定是截然不同的搬磚生涯。
          ▲ 長(zhǎng)按關(guān)注”程序新視界“,洞察技術(shù)內(nèi)幕
          瀏覽 63
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品99久久久久久www | 韩国黄色一区二区三区 免费 | 亚洲精品色哟哟 | 91久久爽无码人妻AⅤ精品蜜桃 | 亚洲AV永久无码精品久久麻豆 |