netty权威指南学习笔记五——分隔符和定长解码器的应用
生活随笔
收集整理的這篇文章主要介紹了
netty权威指南学习笔记五——分隔符和定长解码器的应用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
TCP以流的方式進行數據傳輸,上層應用協議為了對消息進行區分,通常采用以下4中方式:
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权威指南学习笔记五——分隔符和定长解码器的应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【文字检测算法整理】
- 下一篇: JS 时间转化为几分钟前 几小时前 几天