<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之旅 廣告
                使用 Netty 時會遇到需要解碼以分隔符和長度為基礎的協議,本節講解Netty 如何解碼這些協議。 ### [](https://github.com/waylau/essential-netty-in-action/blob/master/CORE%20FUNCTIONS/Decoding%20delimited%20and%20length-based%20protocols.md#分隔符協議)分隔符協議 經常需要處理分隔符協議或創建基于它們的協議,例如[SMTP](http://www.ietf.org/rfc/rfc2821.txt)、[POP3](http://www.ietf.org/rfc/rfc1939.txt)、[IMAP](http://tools.ietf.org/html/rfc3501)、[Telnet](http://tools.ietf.org/search/rfc854)等等。Netty 附帶的解碼器可以很容易的提取一些序列分隔: Table 8.5 Decoders for handling delimited and length-based protocols | 名稱 | 描述 | | --- | --- | | DelimiterBasedFrameDecoder | 接收ByteBuf由一個或多個分隔符拆分,如NUL或換行符 | | LineBasedFrameDecoder | 接收ByteBuf以分割線結束,如"\n"和"\r\n" | 下圖顯示了使用"\r\n"分隔符的處理: [![](https://box.kancloud.cn/2015-08-18_55d3233b51851.jpg)](https://github.com/waylau/essential-netty-in-action/blob/master/images/Figure%208.5%20Handling%20delimited%20frames.jpg) 1. 字節流 2. 第一幀 3. 第二幀 Figure 8.5 Handling delimited frames 下面展示了如何用 LineBasedFrameDecoder 處理 Listing 8.8 Handling line-delimited frames ~~~ public class LineBasedHandlerInitializer extends ChannelInitializer<Channel> { @Override protected void initChannel(Channel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new LineBasedFrameDecoder(65 * 1024)); //1 pipeline.addLast(new FrameHandler()); //2 } public static final class FrameHandler extends SimpleChannelInboundHandler<ByteBuf> { @Override public void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { //3 // Do something with the frame } } } ~~~ 1. 添加一個 LineBasedFrameDecoder 用于提取幀并把數據包轉發到下一個管道中的處理程序,在這種情況下就是 FrameHandler 2. 添加 FrameHandler 用于接收幀 3. 每次調用都需要傳遞一個單幀的內容 使用 DelimiterBasedFrameDecoder 可以方便處理特定分隔符作為數據結構體的這類情況。如下: * 傳入的數據流是一系列的幀,每個由換行(“\n”)分隔 * 每幀包括一系列項目,每個由單個空格字符分隔 * 一幀的內容代表一個“命令”:一個名字后跟一些變量參數 清單8.9中顯示了的實現的方式。定義以下類: * 類 Cmd - 存儲幀的內容,其中一個 ByteBuf 用于存名字,另外一個存參數 * 類 CmdDecoder - 從重寫方法 decode() 中檢索一行,并從其內容中構建一個 Cmd 的實例 * 類 CmdHandler - 從 CmdDecoder 接收解碼 Cmd 對象和對它的一些處理。 所以關鍵的解碼器是擴展了 LineBasedFrameDecoder Listing 8.9 Decoder for the command and the handler ~~~ public class CmdHandlerInitializer extends ChannelInitializer<Channel> { @Override protected void initChannel(Channel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new CmdDecoder(65 * 1024));//1 pipeline.addLast(new CmdHandler()); //2 } public static final class Cmd { //3 private final ByteBuf name; private final ByteBuf args; public Cmd(ByteBuf name, ByteBuf args) { this.name = name; this.args = args; } public ByteBuf name() { return name; } public ByteBuf args() { return args; } } public static final class CmdDecoder extends LineBasedFrameDecoder { public CmdDecoder(int maxLength) { super(maxLength); } @Override protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception { ByteBuf frame = (ByteBuf) super.decode(ctx, buffer); //4 if (frame == null) { return null; //5 } int index = frame.indexOf(frame.readerIndex(), frame.writerIndex(), (byte) ' '); //6 return new Cmd(frame.slice(frame.readerIndex(), index), frame.slice(index +1, frame.writerIndex())); //7 } } public static final class CmdHandler extends SimpleChannelInboundHandler<Cmd> { @Override public void channelRead0(ChannelHandlerContext ctx, Cmd msg) throws Exception { // Do something with the command //8 } } } ~~~ 1. 添加一個 CmdDecoder 到管道;將提取 Cmd 對象和轉發到在管道中的下一個處理器 2. 添加 CmdHandler 將接收和處理 Cmd 對象 3. 命令也是 POJO 4. super.decode() 通過結束分隔從 ByteBuf 提取幀 5. frame 是空時,則返回 null 6. 找到第一個空字符的索引。首先是它的命令名;接下來是參數的順序 7. 從幀先于索引以及它之后的片段中實例化一個新的 Cmd 對象 8. 處理通過管道的 Cmd 對象 ### [](https://github.com/waylau/essential-netty-in-action/blob/master/CORE%20FUNCTIONS/Decoding%20delimited%20and%20length-based%20protocols.md#基于長度的協議)基于長度的協議 基于長度的協議協議在幀頭文件里定義了一個幀編碼的長度,而不是結束位置用一個特殊的分隔符來標記。表8.6列出了 Netty 提供的兩個解碼器,用于處理這種類型的協議。 Table 8.6 Decoders for length-based protocols | 名稱 | 描述 | | --- | --- | | FixedLengthFrameDecoder | 提取固定長度 | | LengthFieldBasedFrameDecoder | 讀取頭部長度并提取幀的長度 | 如下圖所示,FixedLengthFrameDecoder 的操作是提取固定長度每幀8字節 [![](https://box.kancloud.cn/2015-08-18_55d3233e6b826.jpg)](https://github.com/waylau/essential-netty-in-action/blob/master/images/Figure%208.6%20Decoding%20a%20frame%20length%20of%208%20bytes.jpg) 1. 字節流 stream 2. 4個幀,每個幀8個字節 大部分時候幀的大小被編碼在頭部,這種情況可以使用LengthFieldBasedFrameDecoder,它會讀取頭部長度并提取幀的長度。下圖顯示了它是如何工作的: [![](https://box.kancloud.cn/2015-08-18_55d323411d4e7.jpg)](https://github.com/waylau/essential-netty-in-action/blob/master/images/Figure%208.7%20Message%20that%20has%20frame%20size%20encoded%20in%20the%20header.jpg) 1. 長度 "0x000C" (12) 被編碼在幀的前兩個字節 2. 后面的12個字節就是內容 3. 提取沒有頭文件的幀內容 Figure 8.7 Message that has frame size encoded in the header LengthFieldBasedFrameDecoder 提供了幾個構造函數覆蓋各種各樣的頭長字段配置情況。清單8.10顯示了使用三個參數的構造函數是maxFrameLength,lengthFieldOffset lengthFieldLength。在這 情況下,幀的長度被編碼在幀的前8個字節。 Listing 8.10 Decoder for the command and the handler ~~~ public class LineBasedHandlerInitializer extends ChannelInitializer<Channel> { @Override protected void initChannel(Channel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new LineBasedFrameDecoder(65 * 1024)); //1 pipeline.addLast(new FrameHandler()); //2 } public static final class FrameHandler extends SimpleChannelInboundHandler<ByteBuf> { @Override public void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { // Do something with the frame //3 } } } ~~~ 1. 添加一個 LengthFieldBasedFrameDecoder ,用于提取基于幀編碼長度8個字節的幀。 2. 添加一個 FrameHandler 用來處理每幀 3. 處理幀數據 總而言之,本部分探討了 Netty 提供的編解碼器支持協議,包括定義特定的分隔符的字節流的結構或協議幀的長度。這些編解碼器非常有用。
                  <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>

                              哎呀哎呀视频在线观看