TCP是個流協議,所謂流,就是沒有界限的一串數據。你們能夠想一想河裏的流水,是連成一片的,其間並無分界線。TCP底層並不瞭解上層業務數據的具體含義,它會根據TCP緩衝區的實際狀況進行包的劃分,因此在業務上認爲,一個完整的包可能會被TCP拆分紅多個包進行發送,也有可能把多個小的包封裝成一個大的數據包發送,這就是所謂的TCP粘包和拆包問題。app
案例:
源碼分析
某時刻發送端緩衝區太小,致使ABC數據包發生拆包成AB、C,拆分出來的C與數據包DEF粘包發送給接收端。
指針
拆包場景:netty
(1)要發送的數據大於緩衝區剩餘大小;code
(2)待發送的數據大於MSS,TCP會在傳輸前將其拆分;orm
粘包場景:cdn
(1)要發送小於緩衝區剩餘大小;blog
(2)接受數據端的應用層沒來得及讀取緩衝區的數據;繼承
應用層協議存在粘包拆包狀況,netty如何利用Frameecoder來解決的?get
在Netty的codec模塊中,對通用傳輸協議提供了支持,而且在FrameDecoder中對於粘包拆包給出了通用的解決方案,應用層協議解析類能夠經過繼承它而無須擔憂粘包、拆包等問題。
能夠看到http協議解析類HttpMessageDecoder固定、長度解析類FixedLengthFrameDecoder、換行協議解析類LineBaseFrameDecoder等等都是基於FrameDecoder拓展實現,而FrameDecoder繼承自SimpleChannelUpstreamHandler,是否是有點熟悉呢?沒錯,這個在解讀netty3.9的數據處理流程(一)的處理執行者,沒看過的同窗能夠點進去看看。
撥開濃霧:
對於脈絡咱們已經梳理清晰,拆包粘包是前文數據處理流程的某一個環節,那到底FrameDecoder爲何那麼神奇,能通用地處理粘包呢?能夠想象,倉庫包裹打包出庫場景,打包人員在工做臺打包貨物,直到缺乏貨物再讓揀選員揀選過來接着打包,缺貨的時候是否是還有商品在工做臺上,是否是有點懂了FrameDecoder在作什麼事呢?能夠理解就是一個打包工做臺,還無法打包就等待可是注意貨物還在臺上,能夠打包就一直打包下去便可。
那咱們來看看FrameDecoder廬山真面目。
能夠看到cumulation不爲空的狀況下,就調用appendToCumulation將接受到的數據塞到cumulation中,cumulation就是剛剛貨物打包場景中的工做臺,不然就調用callDecode循環地去解析應用數據包,而且調用updateCumulation訂正cumulation的數據。
當cumulation可讀時,記錄下舊的讀指針用於對比,並調用實際的協議執行者解析出應用層數據包。
一、若是數據包爲空而且讀指針未挪動,說明應用層數據包不全,跳出等待數據;
二、若是數據包爲空可是讀指針挪動,拋棄部分數據可能正在讀,繼續調用解析;
三、若是存在數據包而且讀指針未移動,則拋出異常;
四、若是數據包不爲空而且讀指針挪動,很明顯繼續調用解析;
喜歡的讀者能夠關注路上小棧,及時獲取最新的技術文章,專一源碼分析、技術業務思考等。