Netty笔记(二)ChannelHandler和ChannelPipline

Netty所有的数据传输处理都需要在ChannelPipline中的ChannelHandler来处理,这次我们来看看Netty是怎么处理这些数据的。

首先我们需要分清楚什么是出站数据,什么是入站数据。

出站数据:是指你需要发送的数据,不论你是客户端还是服务器只要是写进Channel里的数据都是出站的数据。

入站数据:是指你接收到的数据,不论你是客户端还是服务器,对方写进Channel里的数据,对于你来说都是入站数据。

现在我们来说说看ChannelPipline怎么处理出站数据和入站数据的。

Netty笔记(二)ChannelHandler和ChannelPipline_第1张图片

入站数据都是从头部开始处理,pipline会先调用第一个ChannelInboundHandler,第一个消费后调用fireChannelRead方法触发下一个Handler的channelRead方法,如果不调用fireChannelRead方法,那么数据传递就到此为止。

对于出站数据如果通过调用Channel的write方法写数据的,数据会从Channelpipline的尾端开始传递,会先调用第一个ChannelOutboundHandler,只有Handler调用ChannelHandlerContext的write,才会继续触发下一个Handler,如果调用Channel的write数据将重头开始传递。

我们来定义一个服务端,并打印出日志看一下数据的流转过程

Netty笔记(二)ChannelHandler和ChannelPipline_第2张图片

ServerIn1 的代码如下


@Slf4j
public class ServerInChannelAdapter1 extends ChannelInboundHandlerAdapter {
    
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf in = (ByteBuf) msg;
        log.debug("服务器收到消息:{}",in.toString(CharsetUtil.UTF_8));
        ctx.fireChannelRead(msg);

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        log.debug("服务器读取完成");
        ctx.fireChannelReadComplete();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("服务器异常",cause);
        //关闭连接
        ctx.close();
    }
}

ServerIn2的代码

@Slf4j
public class ServerInChannelAdapter2 extends ChannelInboundHandlerAdapter {
    

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf in = (ByteBuf) msg;
        log.debug("服务器收到消息:{}",in.toString(CharsetUtil.UTF_8));
        //读取完成后需要手动释放
        ReferenceCountUtil.release(in);

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        log.debug("服务器读取完成");
        //从尾部  发送数据
        ctx.channel().writeAndFlush(Unpooled.copiedBuffer("这里是服务器收到请回复",CharsetUtil.UTF_8));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("服务器异常",cause);
        //关闭连接
        ctx.close();
    }
}

ServerOut1  和ServerOut2 代码一样的,代码如下

@Slf4j
public class ServerOutChannelAdapter1 extends ChannelOutboundHandlerAdapter {

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        log.debug("服务器写入数据-> {}", ((ByteBuf) msg).toString(CharsetUtil.UTF_8));
        ctx.write(msg);
        promise.setSuccess();
    }

    @Override
    public void flush(ChannelHandlerContext ctx) throws Exception {
        log.debug("服务器刷新数据");
        ctx.flush();
    }
}

服务器端的Handler添加顺序如下

  public void start() throws InterruptedException {
        //线程组
        group = new NioEventLoopGroup();
        //服务器
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(group)
                //设置非阻塞的服务器Socket连接
                .channel(NioServerSocketChannel.class)
                //绑定端口
                .localAddress(new InetSocketAddress(port))
                .childHandler(new ChannelInitializer() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline()
                                .addLast(new ServerInChannelAdapter1())
                                .addLast(new ServerOutChannelAdapter1())
                                .addLast(new ServerInChannelAdapter2())
                                .addLast(new ServerOutChannelAdapter2());
                    }
                });
        //绑定端口,并获取Channel
        channelFuture = bootstrap.bind().sync();
    }

执行的结果如下

11:25:43.816 [nioEventLoopGroup-2-2] DEBUG com.github.xuejike.javap2p.server.channel.ServerInChannelAdapter1 - 服务器收到消息:这里是客户端,收到请回复
11:25:43.817 [nioEventLoopGroup-2-2] DEBUG com.github.xuejike.javap2p.server.channel.ServerInChannelAdapter2 - 服务器收到消息:这里是客户端,收到请回复
11:25:43.818 [nioEventLoopGroup-2-2] DEBUG com.github.xuejike.javap2p.server.channel.ServerInChannelAdapter1 - 服务器读取完成
11:25:43.818 [nioEventLoopGroup-2-2] DEBUG com.github.xuejike.javap2p.server.channel.ServerInChannelAdapter2 - 服务器读取完成
11:25:43.825 [nioEventLoopGroup-2-2] DEBUG com.github.xuejike.javap2p.server.channel.ServerOutChannelAdapter2 - 服务器写入数据-> 这里是服务器收到请回复
11:25:43.825 [nioEventLoopGroup-2-2] DEBUG com.github.xuejike.javap2p.server.channel.ServerOutChannelAdapter1 - 服务器写入数据-> 这里是服务器收到请回复
11:25:43.826 [nioEventLoopGroup-2-2] DEBUG com.github.xuejike.javap2p.server.channel.ServerOutChannelAdapter2 - 服务器刷新数据
11:25:43.826 [nioEventLoopGroup-2-2] DEBUG com.github.xuejike.javap2p.server.channel.ServerOutChannelAdapter1 - 服务器刷新数据

 

你可能感兴趣的:(Java)