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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

netty权威指南学习笔记五——分隔符和定长解码器的应用

發布時間:2025/5/22 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 netty权威指南学习笔记五——分隔符和定长解码器的应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

    TCP以流的方式進行數據傳輸,上層應用協議為了對消息進行區分,通常采用以下4中方式:

  • 消息長度固定,累計讀取到長度綜合為定長LEN的報文后,就認為讀取到了一個完整的消息,將計數器置位,重新開始讀取下一個數據報;
  • 將回車換行符作為消息結束符,例如FTP協議,這種方式在文本協議中應用比較廣泛;
  • 將特殊的分隔符作為消息的結束標志,回車換行符就是一種特殊的分隔符;
  • 通過在消息頭中定義長度字段來標識消息的總長度。
  •   DelimiterBaseFrameDecoder——分隔符解碼器,FixedLengthFrameDecoder——定長解碼器

    下面我們采用#為分隔符進行代碼練習運行。

    EchoServer服務端代碼

    1 package com.decoder; 2 3 import io.netty.bootstrap.ServerBootstrap; 4 import io.netty.buffer.ByteBuf; 5 import io.netty.buffer.Unpooled; 6 import io.netty.channel.ChannelFuture; 7 import io.netty.channel.ChannelInitializer; 8 import io.netty.channel.ChannelOption; 9 import io.netty.channel.nio.NioEventLoopGroup; 10 import io.netty.channel.socket.SocketChannel; 11 import io.netty.channel.socket.nio.NioServerSocketChannel; 12 import io.netty.handler.codec.DelimiterBasedFrameDecoder; 13 import io.netty.handler.codec.string.StringDecoder; 14 import io.netty.handler.logging.LogLevel; 15 import io.netty.handler.logging.LoggingHandler; 16 17 public class EchoServer { 18 public void bind(int port) throws InterruptedException { 19 NioEventLoopGroup bossGroup = new NioEventLoopGroup(); 20 NioEventLoopGroup workGroup = new NioEventLoopGroup(); 21 try { 22 ServerBootstrap b = new ServerBootstrap(); 23 b.group(bossGroup,workGroup) 24 .channel(NioServerSocketChannel.class) 25 .option(ChannelOption.SO_BACKLOG,100) 26 .childHandler(new LoggingHandler(LogLevel.INFO)) 27 .childHandler(new ChannelInitializer<SocketChannel>() { 28 @Override 29 protected void initChannel(SocketChannel socketChannel) throws Exception { 30 ByteBuf delimiter = Unpooled.copiedBuffer("#".getBytes());//創建一個分隔符,確定為結束標志 31 socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,delimiter)) 32 .addLast(new StringDecoder()) 33 .addLast(new EchoServerHandler()); 34 } 35 }); 36 // 綁定端口,同步等待成功 37 ChannelFuture f = b.bind(port).sync(); 38 // 等待服務端監聽端口關閉 39 f.channel().closeFuture().sync(); 40 } finally { 41 bossGroup.shutdownGracefully(); 42 workGroup.shutdownGracefully(); 43 } 44 } 45 public static void main(String[] args) throws InterruptedException { 46 int port = 8080; 47 if(args.length>0&&args!=null){ 48 port = Integer.parseInt(args[0]); 49 } 50 new EchoServer().bind(port); 51 52 } 53 }

    服務端處理IO代碼

    1 package com.decoder; 2 3 import io.netty.buffer.ByteBuf; 4 import io.netty.buffer.Unpooled; 5 import io.netty.channel.ChannelHandlerContext; 6 import io.netty.channel.ChannelInboundHandlerAdapter; 7 8 public class EchoServerHandler extends ChannelInboundHandlerAdapter { 9 int count; 10 @Override 11 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 12 String body = (String) msg; 13 System.out.println("This is"+ ++count +" times server receive client request."); 14 body += "#"; 15 ByteBuf echo = Unpooled.copiedBuffer(body.getBytes()); 16 ctx.writeAndFlush(echo); 17 } 18 19 @Override 20 public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 21 ctx.flush(); 22 } 23 24 @Override 25 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 26 ctx.close(); 27 } 28 }

    客戶端發送消息代碼

    1 package com.decoder; 2 3 import io.netty.bootstrap.Bootstrap; 4 import io.netty.buffer.ByteBuf; 5 import io.netty.buffer.Unpooled; 6 import io.netty.channel.ChannelFuture; 7 import io.netty.channel.ChannelInitializer; 8 import io.netty.channel.ChannelOption; 9 import io.netty.channel.nio.NioEventLoopGroup; 10 import io.netty.channel.socket.SocketChannel; 11 import io.netty.channel.socket.nio.NioSocketChannel; 12 import io.netty.handler.codec.DelimiterBasedFrameDecoder; 13 import io.netty.handler.codec.string.StringDecoder; 14 15 public class EchoClient { 16 public void connection(int port,String host) throws InterruptedException { 17 NioEventLoopGroup workGroup = new NioEventLoopGroup(); 18 try { 19 Bootstrap b = new Bootstrap(); 20 b.group(workGroup) 21 .channel(NioSocketChannel.class) 22 .option(ChannelOption.TCP_NODELAY,true) 23 .handler(new ChannelInitializer<SocketChannel>() { 24 @Override 25 protected void initChannel(SocketChannel socketChannel) throws Exception { 26 ByteBuf delimiter = Unpooled.copiedBuffer("#".getBytes()); 27 socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,delimiter)) 28 .addLast(new StringDecoder()) 29 .addLast(new EchoClientHandler()); 30 // 31 } 32 }); 33 // 發起異步連接操作 34 ChannelFuture f = b.connect(host,port).sync(); 35 // 等待客戶端鏈路關閉 36 f.channel().closeFuture().sync(); 37 } finally { 38 workGroup.shutdownGracefully(); 39 } 40 } 41 public static void main(String[] args) throws InterruptedException { 42 int port = 8080; 43 if(args.length>0&&args!=null){ 44 System.out.println(args[0]); 45 port = Integer.parseInt(args[0]); 46 } 47 new EchoClient().connection(port,"127.0.0.1"); 48 } 49 }

    客戶端處理IO代碼

    1 package com.decoder; 2 3 import io.netty.buffer.Unpooled; 4 import io.netty.channel.ChannelHandlerContext; 5 import io.netty.channel.ChannelInboundHandlerAdapter; 6 7 public class EchoClientHandler extends ChannelInboundHandlerAdapter { 8 private int count; 9 static final String ECHO_REQ = "hello,zuixiaoyao,welcome here!#"; 10 11 @Override 12 public void channelActive(ChannelHandlerContext ctx) throws Exception { 13 for(int i=0;i<10;i++){ 14 ctx.writeAndFlush(Unpooled.copiedBuffer(ECHO_REQ.getBytes())); 15 } 16 } 17 18 @Override 19 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 20 String body = (String) msg; 21 System.out.println("this is client receive msg"+ ++count +"times:【"+body+"】"); 22 } 23 24 @Override 25 public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 26 super.channelReadComplete(ctx); 27 } 28 29 @Override 30 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 31 super.exceptionCaught(ctx, cause); 32 } 33 }

    運行結果

    服務端

    客戶端

    ?若采用定長解碼器,運行上面代碼看看會發生什么,我們只需要對上面服務器中解碼器換為定長解碼器即可,解碼器最大長度設置為20,看看

    修改的服務端代碼如下:

    1 @Override 2 protected void initChannel(SocketChannel socketChannel) throws Exception { 3 ByteBuf delimiter = Unpooled.copiedBuffer("#".getBytes());//創建一個分隔符,確定為結束標志 4 socketChannel.pipeline() 5 // .addLast(new DelimiterBasedFrameDecoder(1024,delimiter)) 6 // 修改為定長解碼器 7 .addLast(new FixedLengthFrameDecoder(20)) 8 .addLast(new StringDecoder()) 9 .addLast(new EchoServerHandler()); 10 }

    運行后如下:

    服務端結果

    客戶端結果

    我們發現所有運行返回的代碼都不超過20字符。這就是按照定長解析的,但是解析的比較亂,具體的原理還需深入學習后才知道,暫時不表。

    按書上的操作,輸入一行超過20字符的命令請求時,只返回一個20字符定長的數據顯示。

    ?

    轉載于:https://www.cnblogs.com/xiaoyao-001/p/9346628.html

    總結

    以上是生活随笔為你收集整理的netty权威指南学习笔记五——分隔符和定长解码器的应用的全部內容,希望文章能夠幫你解決所遇到的問題。

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