netty handler解碼、編碼的順序
阿新 • • 發佈:2018-12-18
今天來說說netty,給bootstrap注入 handler時,解碼,編碼的觸發順序。
首先寫server
package helloNettyTest2; import java.net.InetAddress; import java.util.List; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.handler.codec.MessageToMessageEncoder; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; public class ServerTest { public static void main(String[] args) throws InterruptedException { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .childHandler(new HelloServerInitializer()); // 伺服器繫結埠監聽 ChannelFuture f = bootstrap.bind(8080).sync(); // 監聽伺服器關閉監聽 f.channel().closeFuture().sync(); // 可以簡寫為 /* b.bind(portNumber).sync().channel().closeFuture().sync(); */ } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } } class HelloServerInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); // 以("\n")為結尾分割的 解碼器 // pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, // Delimiters.lineDelimiter())); // 字串解碼 和 編碼 // pipeline.addLast(new IdleStateHandler(5 ,0, 0, TimeUnit.SECONDS)); pipeline.addLast("encoder", new StringEncoder()); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder1", new encoder1()); pipeline.addLast("encoder2", new encoder2()); pipeline.addLast("decoder1", new decoder1()); pipeline.addLast("decoder2", new decoder2()); // 自己的邏輯Handler pipeline.addLast("handler", new HelloServerHandler()); } } class HelloServerHandler extends SimpleChannelInboundHandler<String> { @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { // 收到訊息直接列印輸出 System.err.println("channelRead0"); System.out.println(ctx.channel().remoteAddress() + " Say : " + msg); // 返回客戶端訊息 - 我已經接收到了你的訊息 ctx.writeAndFlush("Received your message !\n"); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // 收到訊息直接列印輸出 System.err.println("channelRead"); System.out.println(ctx.channel().remoteAddress() + " Say : " + msg); // 返回客戶端訊息 - 我已經接收到了你的訊息 ctx.writeAndFlush("Received your message !\n"); } public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("RamoteAddress : " + ctx.channel().remoteAddress() + " active !"); ctx.writeAndFlush("Welcome to " + InetAddress.getLocalHost().getHostName() + " service!\n"); super.channelActive(ctx); } } class encoder1 extends MessageToMessageEncoder<String> { @Override protected void encode(ChannelHandlerContext paramChannelHandlerContext, String paramI, List<Object> paramList) throws Exception { // TODO Auto-generated method stub System.err.println("encoder1:" + paramI); paramList.add(paramI); } } class encoder2 extends MessageToMessageEncoder<String> { @Override protected void encode(ChannelHandlerContext paramChannelHandlerContext, String paramI, List<Object> paramList) throws Exception { // TODO Auto-generated method stub System.err.println("encoder2:" + paramI); paramList.add(paramI); } } class decoder1 extends MessageToMessageDecoder<String> { @Override protected void decode(ChannelHandlerContext paramChannelHandlerContext, String paramI, List<Object> paramList) throws Exception { System.err.println("decoder1:" + paramI); paramList.add(paramI); } } class decoder2 extends MessageToMessageDecoder<String> { @Override protected void decode(ChannelHandlerContext paramChannelHandlerContext, String paramI, List<Object> paramList) throws Exception { // TODO Auto-generated method stub System.err.println("decoder2:" + paramI); paramList.add(paramI); } }
Chient
package helloNettyTest2; import java.io.IOException; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; public class ClientTest { public static void main(String[] args) throws InterruptedException, IOException { EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap(); bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new HelloClientInitializer()); // 連線服務端 try { // 1. // Channel ch = bootstrap.connect("127.0.0.1", // 8080).sync().channel(); // // 控制檯輸入 // BufferedReader in = new BufferedReader(new // InputStreamReader(System.in)); // for (;;) { // String line = in.readLine(); // if (line == null) { // continue; // } // /* // * 向服務端傳送在控制檯輸入的文字 並用"\r\n"結尾 // * 之所以用\r\n結尾 是因為我們在handler中添加了 DelimiterBasedFrameDecoder 幀解碼。 // * 這個解碼器是一個根據\n符號位分隔符的解碼器。所以每條訊息的最後必須加上\n否則無法識別和解碼 // * */ // ch.writeAndFlush(line + "\r\n"); // } // 2. ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8080).sync(); channelFuture.channel().writeAndFlush("Hello Netty Server ,I am a common client"); channelFuture.channel().closeFuture().sync(); } finally { // The connection is closed automatically on shutdown. eventLoopGroup.shutdownGracefully(); } } } class HelloClientInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch) throws Exception { // TODO Auto-generated method stub /* * 這個地方的 必須和服務端對應上。否則無法正常解碼和編碼 * * 解碼和編碼 我將會在下一張為大家詳細的講解。再次暫時不做詳細的描述 * */ ChannelPipeline pipeline = ch.pipeline(); // pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, // Delimiters.lineDelimiter())); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); // 客戶端的邏輯 pipeline.addLast("handler", new HelloClientHandler()); } } class HelloClientHandler extends SimpleChannelInboundHandler<String> { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client active "); super.channelActive(ctx); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client close "); super.channelInactive(ctx); } @Override protected void channelRead0(ChannelHandlerContext paramChannelHandlerContext, String msg) throws Exception { System.out.println("Server say : " + msg); } } class test1 extends ChannelOutboundHandlerAdapter { }
執行 server、client 結果
會發現解碼的順序是從上往下(StringDecoder、encoder1、encoder2) 而編碼的順序是從下往上的(decoder2、decoder1、StringDecoder)