欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Netty中的DelimiterBasedFrameDecoder使用方法詳解

 更新時間:2023年12月15日 10:41:58   作者:mzjnumber1  
這篇文章主要介紹了Netty中的DelimiterBasedFrameDecoder使用方法詳解,DelimiterBasedFrameDecoder與LineBasedFrameDecoder類似,只不過更加通用,允許我們指定任意特殊字符作為分隔符,我們還可以同時指定多個分隔符,需要的朋友可以參考下

1 DelimiterBasedFrameDecoder介紹

前面介紹了LineBasedFrameDecoder,其以換行符\n或者\r\n作為依據(jù),遇到\n或者\r\n都認為是一條完整的消息。

而DelimiterBasedFrameDecoder與LineBasedFrameDecoder類似,只不過更加通用,允許我們指定任意特殊字符作為分隔符。我們還可以同時指定多個分隔符,如果在請求中發(fā)的確有多個分隔符,將會選擇內(nèi)容最短的一個分隔符作為依據(jù)。 例如:

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

如果我們指定分隔符為\n,那么將會解碼出來2個消息

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

如果我們指定\r\n作為分隔符,那么只會解碼出來一條消息

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

DelimiterBasedFrameDecoder提供了多個構(gòu)造方法,最終調(diào)用的都是以下構(gòu)造方法:

public DelimiterBasedFrameDecoder(
            int maxFrameLength, boolean stripDelimiter, boolean failFast, ByteBuf... delimiters)

其中:

maxLength:

表示一行最大的長度,如果超過這個長度依然沒有檢測到\n或者\r\n,將會拋出TooLongFrameException

failFast:

與maxLength聯(lián)合使用,表示超過maxLength后,拋出TooLongFrameException的時機。如果為true,則超出maxLength后立即拋出TooLongFrameException,不繼續(xù)進行解碼;如果為false,則等到完整的消息被解碼后,再拋出TooLongFrameException異常。

stripDelimiter:

解碼后的消息是否去除分隔符。

delimiters:

分隔符。我們需要先將分割符,寫入到ByteBuf中,然后當做參數(shù)傳入。

需要注意的是,netty并沒有提供一個DelimiterBasedFrameDecoder對應的編碼器實現(xiàn)(筆者沒有找到),因此在發(fā)送端需要自行編碼,添加分隔符。

2 Base64編解碼

對于以特殊字符作為報文分割條件的協(xié)議的解碼器,如:LineBasedFrameDecoder、DelimiterBasedFrameDecoder。

都存在一個典型的問題,如果發(fā)送數(shù)據(jù)當中本身就包含了分隔符,怎么辦?如:我們要發(fā)送的內(nèi)容為:

hello1\nhello2\nhello3\n

我們需要把這個內(nèi)容整體當做一個有效報文來處理,而不是拆分成hello1、hello2、hello3。一些同學可能想到那可以換其他的特殊字符,但是如果內(nèi)容中又包含你想指定的其他特殊字符怎么辦呢?

因此我們通常需要發(fā)送的內(nèi)容進行base64編碼,base64中總共只包含了64個字符。

我們可以指定這64個字符之外的其他字符作為特殊分割字符;而接收端對應的進行base64解碼,得到對應的原始的二進制流,然后進行處理。Netty提供了Base64Encoder/Base64Decoder來幫我們處理這個問題。需要注意的是,只需要對內(nèi)容進行base64編碼,分隔符不需要編碼。

3 DelimiterBasedFrameDecoder結(jié)合Base64編解碼案例

Server端:DelimiterBasedFrameDecoderServer

public class DelimiterBasedFrameDecoderServer {
   public static void main(String[] args) throws Exception {
      EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
      EventLoopGroup workerGroup = new NioEventLoopGroup();
      try {
         ServerBootstrap b = new ServerBootstrap(); // (2)
         b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) // (3)
               .childHandler(new ChannelInitializer<SocketChannel>() { // (4)
                  @Override
                  public void initChannel(SocketChannel ch) throws Exception {
                     ByteBuf delemiter= Unpooled.buffer();
                     delemiter.writeBytes("&".getBytes());
                    //先使用DelimiterBasedFrameDecoder解碼,以&作為分割符
                    ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, true, true,delemiter));
                    //之后使用Base64Decoder對數(shù)據(jù)進行解碼,得到報文的原始的二進制流
                    ch.pipeline().addLast(new Base64Decoder());
                    //對請求報文進行處理
                     ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                        @Override
                        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                           if (msg instanceof ByteBuf) {
                              ByteBuf packet = (ByteBuf) msg;
                              System.out.println(
                                    new Date().toLocaleString() + ":" + packet.toString(Charset.defaultCharset()));
                           }
                        }
                     });
                  }
               });
         // Bind and start to accept incoming connections.
         ChannelFuture f = b.bind(8080).sync(); // (7)
         System.out.println("DelimiterBasedFrameDecoderServer Started on 8080...");
         f.channel().closeFuture().sync();
      } finally {
         workerGroup.shutdownGracefully();
         bossGroup.shutdownGracefully();
      }
   }
}

Server接受到的數(shù)據(jù),首先我們要去除分隔符,然后才能進行base64解碼。因此首選我們添加了DelimiterBasedFrameDecoder根據(jù)&處理粘包辦包問題,之后使用Base64Decoder進行解碼,最后通過一個自定義ChannelInboundHandler打印請求的數(shù)據(jù)。client端:DelimiterBasedFrameDecoderClient

public class DelimiterBasedFrameDecoderClient {
   public static void main(String[] args) throws Exception {
      EventLoopGroup workerGroup = new NioEventLoopGroup();
      try {
         Bootstrap b = new Bootstrap(); // (1)
         b.group(workerGroup); // (2)
         b.channel(NioSocketChannel.class); // (3)
         b.option(ChannelOption.SO_KEEPALIVE, true); // (4)
         b.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
               ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                   //在于server建立連接后,即發(fā)送請求報文
                  public void channelActive(ChannelHandlerContext ctx) {
                     //先對要發(fā)送的原始內(nèi)容進行base64編碼
                     ByteBuf content = Base64.encode(Unpooled.buffer().writeBytes("hello&tianshouzhi&".getBytes
                           ()));
                     //之后添加分隔符
                     ByteBuf req = Unpooled.copiedBuffer(content);
                     req.writeBytes("&".getBytes());
                     ctx.writeAndFlush(req);
                        }
               });
            }
         });
         // Start the client.
         ChannelFuture f = b.connect("127.0.0.1",8080).sync(); // (5)
         // Wait until the connection is closed.
         f.channel().closeFuture().sync();
      } finally {
         workerGroup.shutdownGracefully();
      }
   }
}

在編寫client端代碼時我們先對原始內(nèi)容進行base64編碼,然后添加分割符之后進行輸出。

需要注意,雖然Netty提供了Base64Encoder進行編碼,這里并沒有直接使用,如果直接使用Base64Encoder,那么會對我們輸出的所有內(nèi)容進行編碼,意味著分隔符也會被編碼,這顯然不符合我們的預期,所以這里直接使用了Netty提供了Base64工具類來處理。

如果一定要使用Base64Encoder,那么代碼需要進行相應的修改,自定義的ChannelInboundHandler只輸出原始內(nèi)容,之后通過Base64Encoder進行編碼,然后需要額外再定義一個ChannelOutboundHandler添加分隔符,如:

ch.pipeline().addLast(new ChannelOutboundHandlerAdapter() {
   @Override
   public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
      if(msg instanceof ByteBuf){
         ((ByteBuf) msg).writeBytes("&".getBytes());
      }
   }
});
ch.pipeline().addLast(new Base64Encoder());
ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
    //在于server建立連接后,即發(fā)送請求報文
   public void channelActive(ChannelHandlerContext ctx) {
      ByteBuf req = Unpooled.buffer().writeBytes("hello&tianshouzhi&".getBytes());
      ctx.writeAndFlush(req);
                   }
});

上述兩種方案效果是等價的。

當我們先后啟動server和client后,會看到server端控制臺輸出:

DelimiterBasedFrameDecoderServer Started on 8080...
2018-9-8 13:56:32:hello&tianshouzhi&

說明經(jīng)過base64編碼后,我們的請求中可以包含分隔符作為內(nèi)容。

如果我們將base64編解碼相關(guān)邏輯去掉,你將會看到的輸出是:

DelimiterBasedFrameDecoderServer Started on 8080...
2018-9-8 14:13:31:hello
2018-9-8 14:13:31:tianshouzhi

也就是說,原始內(nèi)容也被誤分割了,解碼失敗,讀者可以自行驗證。

到此這篇關(guān)于Netty中的DelimiterBasedFrameDecoder使用方法詳解的文章就介紹到這了,更多相關(guān)DelimiterBasedFrameDecoder使用方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MyBatis框架中mybatis配置文件詳細介紹

    MyBatis框架中mybatis配置文件詳細介紹

    這篇文章主要介紹了MyBatis框架中mybatis配置文件詳細介紹,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2018-01-01
  • SpringBoot整合MyBatis實現(xiàn)CRUD操作項目實踐

    SpringBoot整合MyBatis實現(xiàn)CRUD操作項目實踐

    本文主要介紹了SpringBoot整合MyBatis實現(xiàn)CRUD操作項目實踐,如何實現(xiàn)數(shù)據(jù)庫的CRUD創(chuàng)建、讀取、更新、刪除操作,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • Spring的初始化和XML解析的實現(xiàn)

    Spring的初始化和XML解析的實現(xiàn)

    這篇文章主要介紹了Spring的初始化和XML解析的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • Maven項目打包成war包部署到Tomcat的方法

    Maven項目打包成war包部署到Tomcat的方法

    這篇文章主要介紹了Maven項目打包成war包部署到Tomcat的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • java異常處理throws完成異常拋出詳解

    java異常處理throws完成異常拋出詳解

    這篇文章主要介紹了java異常處理中throws完成異常拋出示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家學有所得多多進步
    2021-10-10
  • Java視頻斷點上傳的實現(xiàn)示例

    Java視頻斷點上傳的實現(xiàn)示例

    斷點續(xù)傳指的是在下載或上傳時,將下載或上傳任務人為的劃分為幾個部分,本文主要介紹了Java視頻斷點上傳的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • Java?OpenCV圖像處理之SIFT角點檢測詳解

    Java?OpenCV圖像處理之SIFT角點檢測詳解

    SIFT,即尺度不變特征變換,是用于圖像處理領(lǐng)域的一種描述。這種描述具有尺度不變性,可在圖像中檢測出關(guān)鍵點,是一種局部特征描述子。本文將詳細介紹一下Java?OpenCV圖像處理中的SIFT角點檢測,需要的可以參考一下
    2022-02-02
  • Maven打包jar生成javadoc文件和source文件代碼實例

    Maven打包jar生成javadoc文件和source文件代碼實例

    這篇文章主要介紹了Maven打包jar生成javadoc文件和source文件代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • SpringBoot操作Mongodb的實現(xiàn)示例

    SpringBoot操作Mongodb的實現(xiàn)示例

    本文主要介紹了SpringBoot操作Mongodb的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • SpringBoot整合Kafka完成生產(chǎn)消費的方案

    SpringBoot整合Kafka完成生產(chǎn)消費的方案

    網(wǎng)上找了很多管理kafka整合springboot的教程,但是很多都沒辦法應用到生產(chǎn)環(huán)境,很多配置都是缺少,或者不正確的,只能當個demo,所以本文給大家介紹了SpringBoot整合Kafka完成生產(chǎn)消費的方案,需要的朋友可以參考下
    2024-12-12

最新評論