ChannelHandler

  ChannelPipeline

    ChannelPipeline是ChannelHandler实例的列表,用于处理或截获通道的接收和发送数据。ChannelPipeline提供了一种高级的截取过滤模式,让用户可以在ChannelPipeline中完全控制一个事件以及如何处理ChannelHandler与ChannelPipeline的交互。对于每个新的通道,会创建一个新的ChannelPipeline并附加至通道。一旦连接,Channel和ChannelPipeline之间的耦合是永久的。Channel不能附加其他的ChannelPipeline或从ChannelPipeline分离。

    ChannelPipeline是ChannelHandler的一个列表;若一个入站IO事件被触发,这件事会从第一个开始一次通过ChannelPipelie的ChannelHandler,若是一个出站时间,则会从最后一个开始一次通过ChannelPipeline中的ChannelHander。ChannelHandler可以处理事件并检查类型,若某个ChannelHandler不能处理则跳过,并将事件传递给下一个ChannelHandler。ChannelPipeline可以动态添加,删除,替换其中的ChannelHandler。

    修改ChannelPipeline的方法如下:

       addFirst():添加ChannelHandler在ChannelPipeline的第一个位置

      addBefore():在ChannelPipeline中指定的ChannelHandler名称之前添加ChannelHandler

      addAfter():在ChannelPipeline中指定的ChannelHandler名称之后添加ChannelHandler

      addLast():在ChannelPipeline的末尾添加ChannelHandler

      remove():删除ChannelPipeline中指定的ChannelHandler

      replace():替换ChannelPipeline中指定的ChannelHandler

    Netty允许通过一个EventExecutorGroup到每一个ChannelPipeline.add*方法,自定义事件会被包含在EvenetExecutorGroup中的EventExecutor来处理,默认的实现是DefaultEventExecutorGroup。

  ChannelHandlerContext

    每个ChannelHandler被添加到ChannelPipeline后,都会创建一个ChannelHandlerContext并与之创建的ChannelHandler关联绑定。ChannelHandlerContext允许ChannelHandler与其他的ChannelHandler实现进行交互。

    在相同的ChannelPipeline中通过调用ChannelInboundHandler和ChannelOutboundHandler中各个方法中的一个方法来通知最近的handler。可以调用Channel或ChannelPipeline方法让事件流全部通过ChannelPipeline。如是一个入站事件。它始于头部;若是一个出站事件,则始于尾部。

protected void initChannel(SocketChannel ch) throws Exception{
  ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
    public void channelActive(ChannelHandlerContext ctx) throws Exception{
      Channel channel = ctx.channel();
      channel.write(Unpooled.copiedBuffer("netty in action", CharsetUtil.UTF_8));

      ChannelPipeline pipeline = ctx.pipeline();
      pipeline.write(Unpooled.copiedBuffer("netty in action", CharsetUtil.UTF_8));
    }
  });
}

    带有@Sharable注解可以被添加到多个ChannelPipeline。即单个ChannelHandler实例可以有多个ChannelHandlerContext。因此调用不同ChannelHandlerContext可以获取同一ChannelHandler。

    Channel生命周期的四个状态:channelUnregistered,channelRegisterd,channelActive,channelInactive。一个通道在其生命周期内只能连接一次,之后会被回收。重新连接则是创建一个新的通道。

    Netty中有3个实现了ChannelHandler接口的类:ChannelHandlerAdapter,ChannelInboundHandler和ChannelOutboundHandler。

    ChannelHandler提供了在其生命周期内添加或从ChannelPipeline中删除的方法。

      handlerAdded:ChannelHandler添加到实际上下文中准备处理事件

      handlerRemoved:将ChannelHandler从实际上下文中删除,不再处理事件

      exceptionCaught:处理抛出的异常

    这三个方法都需要传递ChannelHandlerContext参数,每个ChannelHandler被添加到ChannelPipeline时会自动创建ChannelHandlerContext。ChannelHandlerContext允许在本地通道安全的存储和检索值。

    ChannelInboundHandler

      ChannelInboundHandler提供了以下方法:

        channelRegistered:ChannelHandlerContext的Channel被注册到EventLoop

        channelUnregistered:ChannelHandlerContext的Channel从EventLoop中注销

        channelActive:ChannelHandlerContext的Channel已经激活

        channelInactive:ChannelHandlerContext的Channel结束生命周期

        channelRead:从当前Channel的对端读取消息

        channelReadComplete:消息读取完成后执行

        userEvenTriggered:一个用户事件被触发

        channelWritabilityChanged:改变通道的可写状态,可以使用Channel.isWritable()检查

        exceptionCaught:重写父类ChannelHandler的方法,处理异常

      ChannelInboundHandlerAdapter的channelRead方法处理完消息后不会释放消息(ReferenceCountUitl.release(msg)),若想自动释放收到的消息,可以使用SimpleChannelInboundHandler<T>。

    ChannelOutboundHandler

       ChannelOutboundHandler提供了以下方法:

        bind:Channel绑定本地地址

        connect:Channel连接操作

        disconnect:Channel断开连接

          close:关闭Channel

        deregister:注销Channel

        read:读取消息,实际上是截获ContextHandlerContext.read()

        write:写操作,实际是通过ChannelPipeline写消息,Channel.flush()属性到实际通道

        flush:刷新消息到通道

    需要注意的是要是放资源和通知ChannelPromise。若ChannelPromise没有被通知可能会导致其中一个ChannelFutureListen不被通知去处理一个消息

    

原文地址:https://www.cnblogs.com/forerver-elf/p/7211236.html