<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # Decoder(解碼器) 本節,會提供幾個類用于 decoder 的實現,并介紹一些具體的例子,這些例子會告訴你什么時候可能用到他們以及怎么來用他們。 Netty 提供了豐富的解碼器抽象基類,我們可以很容易的實現這些基類來自定義解碼器。主要分兩類: - 解碼字節到消息(ByteToMessageDecoder 和 ReplayingDecoder) - 解碼消息到消息(MessageToMessageDecoder) decoder 負責將“入站”數據從一種格式轉換到另一種格式,Netty的解碼器是一種 ChannelInboundHandler 的抽象實現。實踐中使用解碼器很簡單,就是將入站數據轉換格式后傳遞到 ChannelPipeline 中的下一個ChannelInboundHandler 進行處理;這樣的處理是很靈活的,我們可以將解碼器放在 ChannelPipeline 中,重用邏輯。 ### ByteToMessageDecoder ByteToMessageDecoder 是用于將字節轉為消息(或其他字節序列)。 你不能確定遠端是否會一次發送完一個完整的“信息”,因此這個類會緩存入站的數據,直到準備好了用于處理。表7.1說明了它的兩個最重要的方法。 Table 7.1 ByteToMessageDecoder API | 方法名稱 | 描述 | |-----|-----| | Decode | This is the only abstract method you need to implement. It is called with a ByteBuf having the incoming bytes and a List into which decoded messages are added. decode() is called repeatedly until the List is empty on return. The contents of the List are then passed to the next handler in the pipeline. | | decodeLast | The default implementation provided simply calls decode().This method is called once, when the Channel goes inactive. Override to provide special | handling 假設我們接收一個包含簡單整數的字節流,每個都單獨處理。在本例中,我們將從入站 ByteBuf 讀取每個整數并將其傳遞給 pipeline 中的下一個ChannelInboundHandler。“解碼”字節流成整數我們將擴展ByteToMessageDecoder,實現類為“ToIntegerDecoder”,如圖7.1所示。 ![](https://box.kancloud.cn/2015-08-18_55d312925e383.jpg) Figure 7.1 ToIntegerDecoder 每次從入站的 ByteBuf 讀取四個字節,解碼成整形,并添加到一個 List (本例是指 Integer),當不能再添加數據到 lsit 時,它所包含的內容就會被發送到下個 ChannelInboundHandler Listing 7.1 ByteToMessageDecoder that decodes to Integer ~~~ public class ToIntegerDecoder extends ByteToMessageDecoder { //1 @Override public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if (in.readableBytes() >= 4) { //2 out.add(in.readInt()); //3 } } } ~~~ 1. 實現繼承了 ByteToMessageDecode 用于將字節解碼為消息 1. 檢查可讀的字節是否至少有4個 ( int 是4個字節長度) 1. 從入站 ByteBuf 讀取 int , 添加到解碼消息的 List 中 盡管 ByteToMessageDecoder 簡化了這個模式,你會發現它還是有點煩人,在實際的讀操作(這里 readInt())之前,必須要驗證輸入的 ByteBuf 要有足夠的數據。在下一節中,我們將看看 ReplayingDecoder,一個特殊的解碼器。 章節5和6中提到,應該特別注意引用計數。對于編碼器和解碼器來說,這個過程非常簡單。一旦一個消息被編碼或解碼它自動被調用ReferenceCountUtil.release(message) 。如果你稍后還需要用到這個引用而不是馬上釋放,你可以調用 ReferenceCountUtil.retain(message)。這將增加引用計數,防止消息被釋放。 ### ReplayingDecoder ReplayingDecoder 是 byte-to-message 解碼的一種特殊的抽象基類,讀取緩沖區的數據之前需要檢查緩沖區是否有足夠的字節,使用ReplayingDecoder就無需自己檢查;若ByteBuf中有足夠的字節,則會正常讀取;若沒有足夠的字節則會停止解碼。 *ByteToMessageDecoder 和 ReplayingDecoder* *注意到 ReplayingDecoder 繼承自 ByteToMessageDecoder ,所以API 跟表 7.1 是相同的 * 也正因為這樣的包裝使得 ReplayingDecoder 帶有一定的局限性: - 不是所有的標準 ByteBuf 操作都被支持,如果調用一個不支持的操作會拋出 UnreplayableOperationException - ReplayingDecoder 略慢于 ByteToMessageDecoder 如果這些限制是可以接受你可能更喜歡使用 ReplayingDecoder。下面是一個簡單的準則: 如果不引入過多的復雜性 使用 ByteToMessageDecoder 。否則,使用ReplayingDecoder。 Listing 7.2 ReplayingDecoder ~~~ public class ToIntegerDecoder2 extends ReplayingDecoder<Void> { //1 @Override public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { out.add(in.readInt()); //2 } } ~~~ 1. 實現繼承自 ReplayingDecoder 用于將字節解碼為消息 1. 從入站 ByteBuf 讀取整型,并添加到解碼消息的 List 中 如果我們比較清單7.1和7.2很明顯,實現使用 ReplayingDecoder 更簡單。 *更多 Decoder* *下面是更加復雜的使用場景: io.netty.handler.codec.LineBasedFrameDecoder 通過結束控制符("\n" 或 "\r\n").解析入站數據。 io.netty.handler.codec.http.HttpObjectDecoder 用于 HTTP 數據解碼* ### MessageToMessageDecoder 用于從一種消息解碼為另外一種消息(例如,POJO 到 POJO),下表展示了方法: Table 7.2 MessageToMessageDecoder API | 方法名稱 | 描述 | |-----|-----| | decode | decode is the only abstract method you need to implement. It is called for each inbound message to be decoded to another format . The decoded messages are then passed to the next ChannelInboundHandler in the pipeline. | | decodeLast | The default implementation provided simply calls decode().This method is called once, when the Channel goes inactive. Override to provide special | handling 將 Integer 轉為 String,我們提供了 IntegerToStringDecoder,繼承自 MessageToMessageDecoder。 因為這是一個參數化的類,實現的簽名是: ~~~ public class IntegerToStringDecoder extends MessageToMessageDecoder<Integer> ~~~ decode() 方法的簽名是 ~~~ protected void decode( ChannelHandlerContext ctx, Integer msg, List<Object> out ) throws Exception ~~~ 也就是說,入站消息是按照在類定義中聲明的參數類型(這里是 Integer) 而不是 ByteBuf來解析的。在之前的例子,解碼消息(這里是String)將被添加到List ![](https://box.kancloud.cn/2015-08-18_55d3129267629.jpg) Figure 7.2 IntegerToStringDecoder 實現如下: Listing 7.3 MessageToMessageDecoder - Integer to String ~~~ public class IntegerToStringDecoder extends MessageToMessageDecoder<Integer> { //1 @Override public void decode(ChannelHandlerContext ctx, Integer msg, List<Object> out) throws Exception { out.add(String.valueOf(msg)); //2 } } ~~~ 1. 實現繼承自 MessageToMessageDecoder 1. 通過 String.valueOf() 轉換 Integer 消息字符串 正如我們上面指出的,decode()方法的消息參數的類型是由給這個類指定的泛型的類型(這里是Integer)確定的。 *HttpObjectAggregator* *更多復雜的示例,請查看類io.netty.handler.codec.http.HttpObjectAggregator,繼承自MessageToMessageDecoder* ### 在解碼時處理太大的幀 Netty 是異步框架需要緩沖區字節在內存中,直到你能夠解碼它們。因此,你不能讓你的解碼器緩存太多的數據以免耗盡可用內存。為了解決這個共同關心的問題, Netty 提供了一個 TooLongFrameException ,通常由解碼器在幀太長時拋出。 為了避免這個問題,你可以在你的解碼器里設置一個最大字節數閾值,如果超出,將導致 TooLongFrameException 拋出(并由 ChannelHandler.exceptionCaught() 捕獲)。然后由譯碼器的用戶決定如何處理它。雖然一些協議,比如 HTTP、允許這種情況下有一個特殊的響應,有些可能沒有,事件唯一的選擇可能就是關閉連接。 如清單7.4所示 ByteToMessageDecoder 可以利用TooLongFrameException 通知其他 ChannelPipeline 中的 ChannelHandler。 Listing 7.4 SafeByteToMessageDecoder encodes shorts into a ByteBuf ~~~ public class SafeByteToMessageDecoder extends ByteToMessageDecoder { //1 private static final int MAX_FRAME_SIZE = 1024; @Override public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { int readable = in.readableBytes(); if (readable > MAX_FRAME_SIZE) { //2 in.skipBytes(readable); //3 throw new TooLongFrameException("Frame too big!"); } // do something } } ~~~ 1. 實現繼承 ByteToMessageDecoder 來將字節解碼為消息 1. 檢測緩沖區數據是否大于 MAX_FRAME_SIZE 1. 忽略所有可讀的字節,并拋出 TooLongFrameException 來通知 ChannelPipeline 中的 ChannelHandler 這個幀數據超長 這種保護是很重要的,尤其是當你解碼一個有可變幀大小的協議的時候。 到這里我們解釋了解碼器常見用例和 Netty 提供的用于構建它們的抽象基類。但解碼器只是一方面。另一方面,還需要完成 Codec API,我們有編碼器,用于轉換消息到出站數據。這將是我們下一個話題。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看