测试handler的运行过程
1、测试用例包括两个InboundHandler与OuuboundHandler
2、所有的导包都没有在代码中,需要自行添加
1、Demo搭建
2、编写NettyServer
public class NettyServer { public static void main(String[] args) throws InterruptedException {// 创建线程池 接受连接 NioEventLoopGroup bossGroup = new NioEventLoopGroup();// 创建线程池,处理io NioEventLoopGroup workGroup = new NioEventLoopGroup();// 创建服务器端启动助手 ServerBootstrap serverBootstrap = new ServerBootstrap();// 配置启动助手 serverBootstrap.group(bossGroup, workGroup)//设置两个线程池 .channel(NioServerSocketChannel.class)//使用作为服务器端的通道实现 .option(ChannelOption.SO_BACKLOG, 128)//设置线程队列中等待连接的个数 .childOption(ChannelOption.SO_KEEPALIVE, true)//保持活动连接状态 .childHandler(new ChannelInitializer<SocketChannel>() { //创建通道初始化的对象 @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("decoder",new StringDecoder()); pipeline.addLast("encoder",new StringEncoder()); pipeline.addLast(new NettyServerOutHandler()); pipeline.addLast(new NettyServerOutHandler2()); pipeline.addLast(new NettyServerInHandler()); pipeline.addLast(new NettyServerInHandler2()); } }); System.out.println("----------------server is ready--------------------"); ChannelFuture cf = serverBootstrap.bind(9999).sync();//绑定端口,异步 System.out.println("----------------server is starting--------------------");// 关闭通道、关闭通道组 cf.channel().closeFuture().sync(); bossGroup.shutdownGracefully(); workGroup.shutdownGracefully();
}}
3、编写NettyServerInHandler和NettyServerInHandler2
public class NettyServerInHandler extends ChannelInboundHandlerAdapter {
@Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { System.out.println("NettyServerInHandler channelRegistered"); }
@Override public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { System.out.println("NettyServerInHandler channelUnregistered"); }
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("NettyServerInHandler channelActive"); }
@Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("NettyServerInHandler channelInactive"); }
@Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { System.out.println("NettyServerInHandler channelReadComplete"); ctx.channel().writeAndFlush("服务器发送0-0"); }
@Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { System.out.println("NettyServerInHandler userEventTriggered"); }
@Override public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { System.out.println("NettyServerInHandler channelWritabilityChanged"); }
@Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { System.out.println("NettyServerInHandler exceptionCaught"); }
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("NettyServerInHandler channelRead接收到客户端的数据:"+(String)msg);// 事件传播 ctx.fireChannelRead(msg); }}
public class NettyServerInHandler2 extends ChannelInboundHandlerAdapter {
@Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { System.out.println("NettyServerInHandler2 channelRegistered"); }
@Override public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { System.out.println("NettyServerInHandler2 channelUnregistered"); }
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("NettyServerInHandler2 channelActive"); }
@Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("NettyServerInHandler2 channelInactive"); }
@Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { System.out.println("NettyServerInHandler2 channelReadComplete"); ctx.channel().writeAndFlush("服务器发送0-0"); }
@Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { System.out.println("NettyServerInHandler2 userEventTriggered"); }
@Override public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { System.out.println("NettyServerInHandler2 channelWritabilityChanged"); }
@Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { System.out.println("NettyServerInHandler2 exceptionCaught"); }
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("NettyServerInHandler2 channelRead接收到客户端的数据:"+(String)msg); }}
4、编写NettyServerOutHandler与NettyServerOutHandler2
public class NettyServerOutHandler extends ChannelOutboundHandlerAdapter { /** * 写数据 * @param ctx * @param msg * @param promise * @throws Exception */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { System.out.println("ServerOutHandler:"+(String) msg); ctx.write(msg,promise); }}
public class NettyServerOutHandler2 extends ChannelOutboundHandlerAdapter { /** * 写数据 * @param ctx * @param msg * @param promise * @throws Exception */ @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { System.out.println("ServerOutHandler2:"+(String) msg); ctx.write(msg,promise); }}
5、编写NettyClient
public class NettyClient { public static void main(String[] args) throws InterruptedException {// 创建一个线程组 NioEventLoopGroup group = new NioEventLoopGroup(); //2. 创建客户端的启动助手,完成相关配置 Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group)//3. 设置线程组 .channel(NioSocketChannel.class)//4. 设置客户端通道的实现类 .handler(new ChannelInitializer<SocketChannel>() {//5. 创建一个通道初始化对象 @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("encoder",new StringEncoder()); pipeline.addLast("decoder",new StringDecoder()); pipeline.addLast(new NettyClientHandler());//6.往Pipeline链中添加自定义的handler } }); System.out.println("......Client is ready......");
//7.启动客户端去连接服务器端 connect方法是异步的 sync方法是同步阻塞的 ChannelFuture cf = bootstrap.connect("127.0.0.1", 9999).sync();// 发送消息 cf.channel().writeAndFlush("哈哈哈");// 关闭连接 cf.channel().closeFuture().sync();
}}
6、编写NettyClientHandler
public class NettyClientHandler extends SimpleChannelInboundHandler<String> {
/** * 读数据 * @param ctx * @param msg * @throws Exception */ @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { System.out.println("服务器发来消息:"+msg); }}
7、运行结果
服务器端:
----------------server is ready--------------------
----------------server is starting--------------------
NettyServerInHandler channelRegistered
NettyServerInHandler channelActive
NettyServerInHandler channelRead接收到客户端的数据:哈哈哈
NettyServerInHandler2 channelRead接收到客户端的数据:哈哈哈
NettyServerInHandler channelReadComplete
ServerOutHandler2:服务器发送0-0
ServerOutHandler:服务器发送0-0
客户端:
......Client is ready......
服务器发来消息:服务器发送0-0
强制关闭客户端:
NettyServerInHandler channelReadComplete
ServerOutHandler2:服务器发送0-0
ServerOutHandler:服务器发送0-0
NettyServerInHandler exceptionCaught
NettyServerInHandler userEventTriggered
NettyServerInHandler channelInactive
NettyServerInHandler channelUnregistered
8、分析结果
由此可以看出,inboundHandler的执行顺序是:
channelRegistered→channelActive→channelRead→传播到第二个inboundhandler的channelRead
→channelReadComplete→往上一个ServerOutHandler2→再往上ServerOutHandler传播,最后发送到客户端NettyClientInHandler的channelRead中接收到数据。
异常出现的执行顺序:
channelReadComplete→exceptionCaught→userEventTriggered→channelInactive→channelUnregistered。
分析得出:
1、通道先注册再会处于活跃状态
2、通道read结束后才会触发readComplete
3、当inboundHandler中触发一个write方法,就会往该链上的上一个outboundHandler中触发write方法,然后再往上触发,直到没有outboundHandler为止,就会发送消息到客户端。
4、通道关闭会再次触发readComplete,然后触发异常方法exceptionCaught,接下来触发userEventTriggered,最后触发channelInactive与channelUnregistered。
5、readComplete方法是在所有的inboundHandler跑完之后才触发的方法,并且只会触发第一个inboundHandler的readComplete方法。
重磅推荐
想要进群一起学习的小伙伴,快来加小刀微信啦
微信号:best396975802
END
小哥哥小姐姐,
点个在看再走吧~(づ ̄3 ̄)づ╭❤~