最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Netty分布式行解碼器邏輯源碼解析

 更新時間:2022年03月29日 11:02:10   作者:向南是個萬人迷  
這篇文章主要為大家介紹了Netty分布式行解碼器邏輯源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前文傳送門:Netty分布式固定長度解碼器實現(xiàn)原理剖析

這一小節(jié)了解下行解碼器LineBasedFrameDecoder, 行解碼器的功能是一個字節(jié)流, 以\r\n或者直接以\n結尾進行解碼, 也就是以換行符為分隔進行解析

同樣, 這個解碼器也繼承了ByteToMessageDecoder

行解碼器LineBasedFrameDecoder

首先看其參數(shù)

//數(shù)據包的最大長度, 超過該長度會進行丟棄模式
private final int maxLength;
//超出最大長度是否要拋出異常
private final boolean failFast;
//最終解析的數(shù)據包是否帶有換行符
private final boolean stripDelimiter;
//為true說明當前解碼過程為丟棄模式
private boolean discarding;
//丟棄了多少字節(jié)
private int discardedBytes;

其中的丟棄模式, 我們會在源碼中看到其中的含義

我們看其decode方法

protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    Object decoded = decode(ctx, in);
    if (decoded != null) {
        out.add(decoded);
    }
}

這里的decode方法和我們上一小節(jié)分析的decode方法一樣, 調用重載的decode方法, 并將解碼后的內容放到out集合中

我們跟到重載的decode方法中

protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
    //找這行的結尾
    final int eol = findEndOfLine(buffer);
    if (!discarding) {
        if (eol >= 0) {
            final ByteBuf frame;
            //計算從換行符到可讀字節(jié)之間的長度
            final int length = eol - buffer.readerIndex();
            //拿到分隔符長度, 如果是\r\n結尾, 分隔符長度為2
            final int delimLength = buffer.getByte(eol) == '\r'? 2 : 1;
            //如果長度大于最大長度
            if (length > maxLength) {
                //指向換行符之后的可讀字節(jié)(這段數(shù)據完全丟棄)
                buffer.readerIndex(eol + delimLength);
                //傳播異常事件
                fail(ctx, length);
                return null;
            }
            //如果這次解析的數(shù)據是有效的
            //分隔符是否算在完整數(shù)據包里
            //true為丟棄分隔符
            if (stripDelimiter) {
                //截取有效長度
                frame = buffer.readRetainedSlice(length);
                //跳過分隔符的字節(jié)
                buffer.skipBytes(delimLength);
            } else {
                //包含分隔符
                frame = buffer.readRetainedSlice(length + delimLength);
            }

            return frame;
        } else {
            //如果沒找到分隔符(非丟棄模式)
            //可讀字節(jié)長度
            final int length = buffer.readableBytes();
            //如果朝超過能解析的最大長度
            if (length > maxLength) {
                //將當前長度標記為可丟棄的
                discardedBytes = length;
                //直接將讀指針移動到寫指針
                buffer.readerIndex(buffer.writerIndex());
                //標記為丟棄模式
                discarding = true;
                //超過最大長度拋出異常
                if (failFast) {
                    fail(ctx, "over " + discardedBytes);
                }
            }
            //沒有超過, 則直接返回
            return null;
        }
    } else {
        //丟棄模式
        if (eol >= 0) {
            //找到分隔符
            //當前丟棄的字節(jié)(前面已經丟棄的+現(xiàn)在丟棄的位置-寫指針)
            final int length = discardedBytes + eol - buffer.readerIndex();
            //當前換行符長度為多少
            final int delimLength = buffer.getByte(eol) == '\r'? 2 : 1;
            //讀指針直接移到換行符+換行符的長度
            buffer.readerIndex(eol + delimLength);
            //當前丟棄的字節(jié)為0
            discardedBytes = 0;
            //設置為未丟棄模式
            discarding = false;
            //丟棄完字節(jié)之后觸發(fā)異常
            if (!failFast) {
                fail(ctx, length);
            }
        } else {
            //累計已丟棄的字節(jié)個數(shù)+當前可讀的長度
            discardedBytes += buffer.readableBytes();
            //移動
            buffer.readerIndex(buffer.writerIndex());
        }
        return null;
    }
}

 final int eol = findEndOfLine(buffer) 

這里是找當前行的結尾的索引值, 也就是\r\n或者是\n:

6-3-1

圖中不難看出, 如果是以\n結尾的, 返回的索引值是\n的索引值, 如果是\r\n結尾的, 返回的索引值是\r的索引值

我們看findEndOfLine(buffer)方法

private static int findEndOfLine(final ByteBuf buffer) {
    //找到/n這個字節(jié)
    int i = buffer.forEachByte(ByteProcessor.FIND_LF);
    //如果找到了, 并且前面的字符是-r, 則指向/r字節(jié)
    if (i > 0 && buffer.getByte(i - 1) == '\r') {
        i--;
    }
    return i;
}

這里通過一個forEachByte方法找\n這個字節(jié), 如果找到了, 并且前面是\r, 則返回\r的索引, 否則返回\n的索引

回到重載的decode方法中:

 if (!discarding) 判斷是否為非丟棄模式, 默認是就是非丟棄模式, 所以進入if中

 if (eol >= 0) 如果找到了換行符, 我們看非丟棄模式下找到換行符的相關邏輯:

final ByteBuf frame; 
final int length = eol - buffer.readerIndex();
final int delimLength = buffer.getByte(eol) == '\r'? 2 : 1; 
if (length > maxLength) {
    buffer.readerIndex(eol + delimLength);
    fail(ctx, length);
    return null;
} 
if (stripDelimiter) { 
    frame = buffer.readRetainedSlice(length); 
    buffer.skipBytes(delimLength);
} else { 
    frame = buffer.readRetainedSlice(length + delimLength);
}
return frame;

首先獲得換行符到可讀字節(jié)之間的長度, 然后拿到換行符的長度, 如果是\n結尾, 那么長度為1, 如果是\r結尾, 長度為2

 if (length > maxLength) 帶表如果長度超過最大長度, 則直接通過 readerIndex(eol + delimLength) 這種方式, 將讀指針指向換行符之后的字節(jié), 說明換行符之前的字節(jié)需要完全丟棄

6-3-2

丟棄之后通過fail方法傳播異常, 并返回null

繼續(xù)往下看, 走到下一步, 說明解析出來的數(shù)據長度沒有超過最大長度, 說明是有效數(shù)據包

 if (stripDelimiter) 表示是否要將分隔符放在完整數(shù)據包里面, 如果是true, 則說明要丟棄分隔符, 然后截取有效長度, 并跳過分隔符長度

將包含分隔符進行截取

以上就是非丟棄模式下找到換行符的相關邏輯

我們再看非丟棄模式下沒有找到換行符的相關邏輯, 也就是非丟棄模式下,  if (eol >= 0) 中的else塊:

final int length = buffer.readableBytes();
if (length > maxLength) { 
    discardedBytes = length; 
    buffer.readerIndex(buffer.writerIndex());
    discarding = true; 
    if (failFast) {
        fail(ctx, "over " + discardedBytes);
    }
} 
return null;

首先通過 final int length = buffer.readableBytes() 獲取所有的可讀字節(jié)數(shù)

然后判斷可讀字節(jié)數(shù)是否超過了最大值, 如果超過最大值, 則屬性discardedBytes標記為這個長度, 代表這段內容要進行丟棄

6-3-3

 buffer.readerIndex(buffer.writerIndex()) 這里直接將讀指針移動到寫指針, 并且將discarding設置為true, 就是丟棄模式

如果可讀字節(jié)沒有超過最大長度, 則返回null, 表示什么都沒解析出來, 等著下次解析

我們再看丟棄模式的處理邏輯, 也就是 if (!discarding) 中的else塊:

首先這里也分兩種情況, 根據 if (eol >= 0) 判斷是否找到了分隔符, 我們首先看找到分隔符的解碼邏輯:

final int length = discardedBytes + eol - buffer.readerIndex();
final int delimLength = buffer.getByte(eol) == '\r'? 2 : 1;
buffer.readerIndex(eol + delimLength);
discardedBytes = 0;
discarding = false;
if (!failFast) {
    fail(ctx, length);
}

如果找到換行符, 則需要將換行符之前的數(shù)據全部丟棄掉

6-3-4

 final int length = discardedBytes + eol - buffer.readerIndex() 

這里獲得丟棄的字節(jié)總數(shù), 也就是之前丟棄的字節(jié)數(shù)+現(xiàn)在需要丟棄的字節(jié)數(shù)

然后計算換行符的長度, 如果是\n則是1, \r\n就是2

 buffer.readerIndex(eol + delimLength) 

這里將讀指針移動到換行符之后的位置

然后將discarding設置為false, 表示當前是非丟棄狀態(tài)

我們再看丟棄模式未找到換行符的情況, 也就是丟棄模式下,  if (eol >= 0) 中的else塊:

discardedBytes += buffer.readableBytes();
buffer.readerIndex(buffer.writerIndex());

這里做的事情非常簡單, 就是累計丟棄的字節(jié)數(shù), 并將讀指針移動到寫指針, 也就是將數(shù)據全部丟棄

最后在丟棄模式下, decode方法返回null, 代表本次沒有解析出任何數(shù)據

以上就是行解碼器的相關邏輯

以上就是Netty分布式行解碼器邏輯源碼解析的詳細內容,更多關于Netty分布式行解碼器的資料請關注腳本之家其它相關文章!

相關文章

  • Spring中的ContextLoaderListener詳細解析

    Spring中的ContextLoaderListener詳細解析

    這篇文章主要介紹了Spring中的ContextLoaderListener詳細解析,在web容器即Tomact容器啟動web應用即servlet應用時,會觸發(fā)ServletContextEvent時間,這個事件會被ServletContextListener監(jiān)聽,需要的朋友可以參考下
    2023-12-12
  • Java初始化List方法代碼實例

    Java初始化List方法代碼實例

    這篇文章主要介紹了Java初始化List方法代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • 如何解決Webservice第一次訪問特別慢的問題

    如何解決Webservice第一次訪問特別慢的問題

    這篇文章主要介紹了如何解決Webservice第一次訪問特別慢的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java springboot項目jar發(fā)布過程解析

    Java springboot項目jar發(fā)布過程解析

    這篇文章主要介紹了Java springboot項目jar發(fā)布過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • Java?NIO下ByteBuffer的常用方法學習

    Java?NIO下ByteBuffer的常用方法學習

    這篇文章主要帶大家來初步學習一下NIO?中的?ByteBuffer的應用與常用方法,文中的示例代碼講解詳細,對我們深入學習Java有一定的幫助,感興趣的可以了解一下
    2023-05-05
  • 哈希表在算法題目中的實際應用詳解(Java)

    哈希表在算法題目中的實際應用詳解(Java)

    散列表(Hash?table,也叫哈希表)是根據關鍵碼值(Key?value)而直接進行訪問的數(shù)據結構,下面這篇文章主要給大家介紹了關于哈希表在算法題目中的實際應用,文中介紹的方法是Java,需要的朋友可以參考下
    2024-03-03
  • 詳解Java的Hibernate框架中的Interceptor和Collection

    詳解Java的Hibernate框架中的Interceptor和Collection

    這篇文章主要介紹了Java的Hibernate框架中的Interceptor和Collection,Hibernate是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下
    2016-01-01
  • centos7安裝java的多種方式總結

    centos7安裝java的多種方式總結

    這篇文章主要給大家介紹了關于centos7安裝java的多種方式,文中通過實例代碼以及圖文介紹的非常詳細,對大家學習或者使用java具有一定的參考學習價值,需要的朋友可以參考下
    2023-01-01
  • Spring中@PathVariable和@RequestParam注解的用法區(qū)別

    Spring中@PathVariable和@RequestParam注解的用法區(qū)別

    這篇文章主要介紹了Spring中@PathVariable和@RequestParam注解的用法區(qū)別,@PathVariable 是 Spring 框架中的一個注解,用于將 URL 中的變量綁定到方法的參數(shù)上,它通常用于處理 RESTful 風格的請求,從 URL 中提取參數(shù)值,并將其傳遞給方法進行處理,需要的朋友可以參考下
    2024-01-01
  • Java中將MultipartFile和File互轉的方法詳解

    Java中將MultipartFile和File互轉的方法詳解

    我們在開發(fā)過程中經常需要接收前端傳來的文件,通常需要處理MultipartFile格式的文件,今天來介紹一下MultipartFile和File怎么進行優(yōu)雅的互轉,需要的朋友可以參考下
    2023-10-10

最新評論

万年县| 项城市| 阳江市| 那坡县| 丰城市| 满城县| 观塘区| 福贡县| 陆丰市| 西青区| 文成县| 达日县| 金门县| 阆中市| 木里| 沂水县| 永定县| 乾安县| 沅江市| 镇巴县| 清镇市| 河北区| 隆德县| 礼泉县| 宜川县| 罗平县| 准格尔旗| 阆中市| 乐昌市| 株洲市| 霍邱县| 双鸭山市| 潢川县| 怀柔区| 叙永县| 乐昌市| 双鸭山市| 凤凰县| 石河子市| 博白县| 贵德县|