最近在学netty4,原因是netty5被netty放弃了,不过在学习过程中,由于半吊子,对handler的执行顺序有很不明白,看了网上的资料也不明白,虽然说了in的情况是按照进入pipeline的顺序执行,而out是逆序执行,但是写起来,运行起来还是有异常,这个是写做出来的问题,今天记录下过程,首先声明本章不应该作为开发的使用,因为,本身是错误的(不能说错误,但是不对),只是服务端,客户端,随便用一个即可
public class WangNetty4Server {
private static final Logger LOGGER = LoggerFactory.getLogger(WangNetty4Server.class);
public void start(int port){
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
try {
bootstrap.group(boss, work)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
// .option(ChannelOption.SO_TIMEOUT, 5 * 1000)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.SO_RCVBUF, 10 * 1024)
.childOption(ChannelOption.SO_SNDBUF, 10 * 1024)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel sc) throws Exception {
sc.pipeline().addLast(new WangInHandler1());
sc.pipeline().addLast(new WangInHandler2());
// sc.pipeline().addLast(new WangInHandler3());
}
});
ChannelFuture future = bootstrap.bind(port).sync();
future.channel().closeFuture().sync();
} catch (Exception e) {
LOGGER.error("server 启动失败",e);
}finally{
boss.shutdownGracefully();
work.shutdownGracefully();
}
}
public static void main(String[] args) {
WangNetty4Server server = new WangNetty4Server();
server.start(8085);
}
}
public class WangInHandler1 extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
// TODO Auto-generated method stub
// super.channelRead(ctx, msg);
System.out.println(" WangInHandler1 channelRead");
ctx.fireChannelRead(msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelReadComplete(ctx);
System.out.println(" WangInHandler1 channelReadComplete");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
// TODO Auto-generated method stub
super.exceptionCaught(ctx, cause);
System.out.println(" WangInHandler1 exceptionCaught");
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelActive(ctx);
System.out.println(" WangInHandler1 channelActive");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelInactive(ctx);
System.out.println(" WangInHandler1 channelInactive");
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelRegistered(ctx);
System.out.println(" WangInHandler1 channelRegistered");
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelUnregistered(ctx);
System.out.println(" WangInHandler1 channelUnregistered");
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx)
throws Exception {
// TODO Auto-generated method stub
super.channelWritabilityChanged(ctx);
System.out.println(" WangInHandler1 channelWritabilityChanged");
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
throws Exception {
// TODO Auto-generated method stub
super.userEventTriggered(ctx, evt);
System.out.println(" WangInHandler1 userEventTriggered");
}
}
public class WangInHandler2 extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
// TODO Auto-generated method stub
// super.channelRead(ctx, msg);
System.out.println(" WangInHandler2 channelRead");
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelReadComplete(ctx);
System.out.println(" WangInHandler2 channelReadComplete");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
// TODO Auto-generated method stub
super.exceptionCaught(ctx, cause);
System.out.println(" WangInHandler2 exceptionCaught");
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelActive(ctx);
System.out.println(" WangInHandler2 channelActive");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelInactive(ctx);
System.out.println(" WangInHandler2 channelInactive");
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelRegistered(ctx);
System.out.println(" WangInHandler2 channelRegistered");
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelUnregistered(ctx);
System.out.println(" WangInHandler2 channelUnregistered");
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx)
throws Exception {
// TODO Auto-generated method stub
super.channelWritabilityChanged(ctx);
System.out.println(" WangInHandler2 channelWritabilityChanged");
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
throws Exception {
// TODO Auto-generated method stub
super.userEventTriggered(ctx, evt);
System.out.println(" WangInHandler2 userEventTriggered");
}
}
public class WangInHandler3 extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
// TODO Auto-generated method stub
// super.channelRead(ctx, msg);
System.out.println(" WangInHandler3 channelRead");
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelReadComplete(ctx);
System.out.println(" WangInHandler3 channelReadComplete");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
// TODO Auto-generated method stub
super.exceptionCaught(ctx, cause);
System.out.println(" WangInHandler3 exceptionCaught");
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelActive(ctx);
System.out.println(" WangInHandler3 channelActive");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelInactive(ctx);
System.out.println(" WangInHandler3 channelInactive");
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelRegistered(ctx);
System.out.println(" WangInHandler3 channelRegistered");
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelUnregistered(ctx);
System.out.println(" WangInHandler3 channelUnregistered");
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx)
throws Exception {
// TODO Auto-generated method stub
super.channelWritabilityChanged(ctx);
System.out.println(" WangInHandler3 channelWritabilityChanged");
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
throws Exception {
// TODO Auto-generated method stub
super.userEventTriggered(ctx, evt);
System.out.println(" WangInHandler3 userEventTriggered");
}
}
大家看到了,我实现的是ChannelInboundHandlerAdapter方法,每个方法中先super(),然后打印System.out
先说明1)channelRead()方法需要使用ctx.fireChannelRead(msg);才会向下一个inhandler,传递,也就是super.channelRead(ctx, msg);,其实super的这个方法,就是ctx.fireChannelRead(msg);
执行结果
WangInHandler2 channelRegistered
WangInHandler1 channelRegistered
WangInHandler2 channelActive
WangInHandler1 channelActive
WangInHandler1 channelRead
WangInHandler2 channelRead
WangInHandler2 channelReadComplete
WangInHandler1 channelReadComplete
下面是客户端主动停止报的异常
WangInHandler2 channelReadComplete[nioEventLoopGroup-3-1] WARN io.netty.channel.DefaultChannelPipeline - An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
WangInHandler1 channelReadComplete
java.io.IOException: Connection reset by peer
at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:192)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:379)
at io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:288)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1108)
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:345)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:148)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:745)
WangInHandler2 exceptionCaught
WangInHandler1 exceptionCaught
WangInHandler2 channelInactive
WangInHandler1 channelInactive
WangInHandler2 channelUnregistered
WangInHandler1 channelUnregistered
大家从日志中看到,似乎与网上说的先进先出,不一致,只有channelread()是一致的,我当时也是这样认为的,其实这个是错误的,原因是我的写作方法问题,应该是先执行我们自己的方法,然后在super方法,之所以channelread显示对,因为
System.out.println(" WangInHandler1 channelRead");
ctx.fireChannelRead(msg);我先打印后执行了super方法
本例子不对,看下一例子