netty handler解码、编码的顺序
今天来说说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)