日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

netty系列之:内置的Frame detection

發布時間:2024/2/28 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 netty系列之:内置的Frame detection 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 簡介
  • Frame detection
    • DelimiterBasedFrameDecoder
    • FixedLengthFrameDecoder
    • LengthFieldBasedFrameDecoder
    • LineBasedFrameDecoder
  • 總結

簡介

上篇文章我們講到了netty中怎么自定義編碼和解碼器,但是自定義實現起來還是挺復雜的,一般沒有特殊必要的情況下,大家都希望越簡單越好,其難點就是找到ByteBuf中的分割點,將ByteBuf分割成為一個個的可以處理的單元。今天本文講講netty中自帶的分割處理機制。

Frame detection

在上一章,我們提到了需要有一種手段來區分ByteBuf中不同的數據,也就是說找到ByteBuf中不同數據的分割點。如果首先將ByteBuf分割成一個個的獨立的ByteBuf,再對獨立的ByteBuf進行處理就會簡單很多。

netty中提供了4個分割點的編碼器,我們可以稱之為Frame detection,他們分別是DelimiterBasedFrameDecoder, FixedLengthFrameDecoder, LengthFieldBasedFrameDecoder, 和 LineBasedFrameDecoder。

這幾個類都是ByteToMessageDecoder的子類,接下來我們一一進行介紹。

DelimiterBasedFrameDecoder

首先是DelimiterBasedFrameDecoder,看名字就知道這個是根據delimiter對bytebuf進行分割的解碼器。什么是delimiter呢?

netty中有一個Delimiters類,專門定義分割的字符,主要有兩個delimiter,分別是nulDelimiter和lineDelimiter:

public static ByteBuf[] nulDelimiter() {return new ByteBuf[] {Unpooled.wrappedBuffer(new byte[] { 0 }) };}public static ByteBuf[] lineDelimiter() {return new ByteBuf[] {Unpooled.wrappedBuffer(new byte[] { '\r', '\n' }),Unpooled.wrappedBuffer(new byte[] { '\n' }),};}

nullDelimiter用來處理0x00,主要用來處理Flash XML socket或者其他的類似的協議。

lineDelimiter用來處理回車和換行符,主要用來文本文件的處理中。

對于DelimiterBasedFrameDecoder來說,如果有多個delimiter的話,會選擇將ByteBuf分割最短的那個,舉個例子,如果我們使用DelimiterBasedFrameDecoder(Delimiters.lineDelimiter()) ,因為lineDelimiter中實際上有兩個分割方式,回車+換行或者換行,如果遇到下面的情況:

+--------------+| ABC\nDEF\r\n |+--------------+

DelimiterBasedFrameDecoder會選擇最短的分割結果,也就說將上面的內容分割成為:

+-----+-----+| ABC | DEF |+-----+-----+

而不是

+----------+| ABC\nDEF |+----------+

FixedLengthFrameDecoder

這個類會將ByteBuf分成固定的長度,比如收到了下面的4塊byte信息:

+---+----+------+----+| A | BC | DEFG | HI |+---+----+------+----+

如果使用一個FixedLengthFrameDecoder(3) ,則會將上面的ByteBuf分成下面的幾個部分:

+-----+-----+-----+| ABC | DEF | GHI |+-----+-----+-----+

LengthFieldBasedFrameDecoder

這個類就更加靈活一點,可以根據數據中的length字段取出后續的byte數組。LengthFieldBasedFrameDecoder非常靈活,它有4個屬性來控制他們分別是lengthFieldOffset、lengthFieldLength、lengthAdjustment和initialBytesToStrip。

lengthFieldOffset是長度字段的起始位置,lengthFieldLength是長度字段本身的長度,lengthAdjustment是對目標數據長度進行調整,initialBytesToStrip是解密過程中需要刪除的byte數目。理解不了?沒關系,我們來舉幾個例子。

首先看一個最簡單的:

lengthFieldOffset = 0lengthFieldLength = 2lengthAdjustment = 0initialBytesToStrip = 0 BEFORE DECODE (14 bytes) AFTER DECODE (14 bytes)+--------+----------------+ +--------+----------------+| Length | Actual Content |----->| Length | Actual Content || 0x000C | "HELLO, WORLD" | | 0x000C | "HELLO, WORLD" |+--------+----------------+ +--------+----------------+

上面的設置表示,length是從第0位開始的,長度是2個字節。其中Ox00C=12, 這也是“HELLO, WORLD” 的長度。

如果不想要Length字段,可以通過設置initialBytesToStrip把length刪除:

lengthFieldOffset = 0lengthFieldLength = 2lengthAdjustment = 0initialBytesToStrip = 2 (= length 字段的長度)BEFORE DECODE (14 bytes) AFTER DECODE (12 bytes)+--------+----------------+ +----------------+| Length | Actual Content |----->| Actual Content || 0x000C | "HELLO, WORLD" | | "HELLO, WORLD" |+--------+----------------+ +----------------+

lengthAdjustment是對Length字段的值進行調整,因為在有些情況下Length字段可能包含了整條數據的長度,也就是Length+內容,所以需要在解析的時候進行調整,比如下面的例子,真實長度其實是0x0C,但是傳入的卻是0x0E,所以需要減去Length字段的長度2,也就是將lengthAdjustment設置為-2。

lengthFieldOffset = 0lengthFieldLength = 2lengthAdjustment = -2 (= Length字段的長度)initialBytesToStrip = 0BEFORE DECODE (14 bytes) AFTER DECODE (14 bytes)+--------+----------------+ +--------+----------------+| Length | Actual Content |----->| Length | Actual Content || 0x000E | "HELLO, WORLD" | | 0x000E | "HELLO, WORLD" |+--------+----------------+ +--------+----------------+

LineBasedFrameDecoder

LineBasedFrameDecoder專門處理文本文件中的一行結束。也就是 “\n” 和 “\r\n”,他和DelimiterBasedFrameDecoder很類似,但是DelimiterBasedFrameDecoder更加通用。

總結

有了上面4個Frame detection裝置之后,就可以在pipline中首先添加這些Frame detection,然后再添加自定義的handler,這樣在自定義的handler中就不用考慮讀取ByteBuf的長度問題了。

比如在StringDecoder中,如果已經使用了 LineBasedFrameDecoder , 那么在decode方法中可以假設傳入的ByteBuf就是一行字符串,那么可以直接這樣使用:

protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {out.add(msg.toString(charset));}

是不是很簡單?

本文已收錄于 http://www.flydean.com/15-netty-buildin-frame-detection/

最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程序那些事」,懂技術,更懂你!

總結

以上是生活随笔為你收集整理的netty系列之:内置的Frame detection的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。