Netty如何解決粘包拆包?(二)

路上小棧發表於2019-05-01

Netty如何解決粘包拆包?(二)

前言

TCP是個流協議,所謂流,就是沒有界限的一串資料。大家可以想想河裡的流水,是連成一片的,其間並沒有分界線。TCP底層並不瞭解上層業務資料的具體含義,它會根據TCP緩衝區的實際情況進行包的劃分,所以在業務上認為,一個完整的包可能會被TCP拆分成多個包進行傳送,也有可能把多個小的包封裝成一個大的資料包傳送,這就是所謂的TCP粘包和拆包問題。

案例:

          Netty如何解決粘包拆包?(二)

       某時刻傳送端緩衝區過小,導致ABC資料包發生拆包成AB、C,拆分出來的C與資料包DEF粘包傳送給接收端。

拆包場景:

(1)要傳送的資料大於緩衝區剩餘大小;

(2)待傳送的資料大於MSS,TCP會在傳輸前將其拆分;

粘包場景:

(1)要傳送小於緩衝區剩餘大小;

(2)接受資料端的應用層沒來得及讀取緩衝區的資料;

應用層協議存在粘包拆包情況,netty如何利用Frameecoder來解決的?

在Netty的codec模組中,對通用傳輸協議提供了支援,並且在FrameDecoder中對於粘包拆包給出了通用的解決方案,應用層協議解析類可以通過繼承它而無須擔心粘包、拆包等問題。

Netty如何解決粘包拆包?(二)

        可以看到http協議解析類HttpMessageDecoder固定、長度解析類FixedLengthFrameDecoder、換行協議解析類LineBaseFrameDecoder等等都是基於FrameDecoder擴充實現,而FrameDecoder繼承自SimpleChannelUpstreamHandler,是不是有點熟悉呢?沒錯,這個在解讀netty3.9的資料處理流程(一)的處理執行者,沒看過的同學可以點進去看看。

撥開濃霧:

         對於脈絡我們已經梳理清晰,拆包粘包是前文資料處理流程的某一個環節,那到底FrameDecoder為什麼那麼神奇,能通用地處理粘包呢?可以想象,倉庫包裹打包出庫場景,打包人員在工作臺打包貨物,直到缺少貨物再讓揀選員揀選過來接著打包,缺貨的時候是不是還有商品在工作臺上,是不是有點懂了FrameDecoder在做什麼事呢?可以理解就是一個打包工作臺,還沒法打包就等待但是注意貨物還在臺上,可以打包就一直打包下去即可。

那我們來看看FrameDecoder廬山真面目。

Netty如何解決粘包拆包?(二)

       可以看到cumulation不為空的情況下,就呼叫appendToCumulation將接受到的資料塞到cumulation中,cumulation就是剛剛貨物打包場景中的工作臺,否則就呼叫callDecode迴圈地去解析應用資料包,並且呼叫updateCumulation訂正cumulation的資料。

Netty如何解決粘包拆包?(二)

       當cumulation可讀時,記錄下舊的讀指標用於對比,並呼叫實際的協議執行者解析出應用層資料包。

       1、如果資料包為空並且讀指標未挪動,說明應用層資料包不全,跳出等待資料;

       2、如果資料包為空但是讀指標挪動,拋棄部分資料可能正在讀,繼續呼叫解析;

       3、如果存在資料包並且讀指標未移動,則丟擲異常;

       4、如果資料包不為空並且讀指標挪動,很明顯繼續呼叫解析;


       喜歡的讀者可以關注路上小棧,及時獲取最新的技術文章,專注原始碼分析、技術業務思考等。

Netty如何解決粘包拆包?(二)


相關文章