一起学netty(12)ChannelInboundHandler和ChannelOutboundHandler处理器

weblog 703 0 0

ChannelInboundHandler

ChannelInboundHandler是入栈消息处理的核心接口,如下:

public interface ChannelInboundHandler extends ChannelHandler {
   void channelRegistered(ChannelHandlerContext var1) throws Exception;
   void channelUnregistered(ChannelHandlerContext var1) throws Exception;
   void channelActive(ChannelHandlerContext var1) throws Exception;
   void channelInactive(ChannelHandlerContext var1) throws Exception;
   void channelRead(ChannelHandlerContext var1, Object var2) throws Exception;
   void channelReadComplete(ChannelHandlerContext var1) throws Exception;
   void userEventTriggered(ChannelHandlerContext var1, Object var2) throws Exception;
   void channelWritabilityChanged(ChannelHandlerContext var1) throws Exception;
   void exceptionCaught(ChannelHandlerContext var1, Throwable var2) throws Exception;
}

其主要方法描述如下:

  1. channelRegistered: 当一个Channel注册到EventLoop上,可以处理I/O时被调用
  2. channelUnregistered: 当一个Channel从它的EventLoop上解除注册,不再处理I/O时被调用
  3. channelActive: 当Channel变成活跃状态时被调用;Channel是连接/绑定、就绪的
  4. channelInactive: 当Channel离开活跃状态,不再连接到某个远端时被调用
  5. channelReadComplete: 当Channel上的某个读操作完成时被调用
  6. channelRead: 当从Channel中读数据时被调用
  7. channelWritabilityChanged: 当Channel的可写状态改变时被调用。通过这个方法,用户可以确保写操作不会进行地太快(避免OutOfMemoryError)或者当Channel又变成可写时继续写操作。Channel类的isWritable()方法可以用来检查Channel的可写状态。可写性的阈值可以通过Channel.config().setWriteHighWaterMark()和Channel.config().setWriteLowWaterMark()来设定。
  8. userEventTriggered: 因某个POJO穿过ChannelPipeline引发ChannelnboundHandler.fireUserEventTriggered()时被调用。

一般我们在自定义消息处理器的时候通常会实现ChannelInboundHandler的一个子类ChannelInboundHandlerAdapter,它默认实现了调用下一个处理器的方法。

//入栈消息处理器
pipeline.addLast(new ChannelInboundHandlerAdapter(){
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println(msg.getClass());
        //释放内存
        ReferenceCountUtil.release(msg);
    }
});

可以看到,当消息处理器继承ChannelInboundHandlerAdapter类时并且msg的类型是ByteBuf类型时,需要执行ReferenceCountUtil.release(msg);方法手动释放ByteBuf的内存,因为ByteBuf使用的是直接内存。

为了避免上述情况的发生,我们还可以继承SimpleChannelInboundHandler类,如下:

//入栈消息处理器
pipeline.addLast(new SimpleChannelInboundHandler<ByteBuf>(){
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf msg) throws Exception {
        System.out.println(msg);
    }
});

它实际上是ChannelInboundHandlerAdapter的子类,它在实现channelRead方法时对ByteBuf进行了处理。

ChannelOutboundHandler

ChannelOutboundHandler是出栈消息处理的核心接口,一般在做回写数据的消息编码时会用到。它的子类一般都是各种编码器,如StringEncoderMessageToMessageEncoderProtobufEncoderHttpRequestEncoder等。

public interface ChannelOutboundHandler extends ChannelHandler {
    void bind(ChannelHandlerContext var1, SocketAddress var2, ChannelPromise var3) throws Exception;
    void connect(ChannelHandlerContext var1, SocketAddress var2, SocketAddress var3, ChannelPromise var4) throws Exception;
    void disconnect(ChannelHandlerContext var1, ChannelPromise var2) throws Exception;
    void close(ChannelHandlerContext var1, ChannelPromise var2) throws Exception;
    void deregister(ChannelHandlerContext var1, ChannelPromise var2) throws Exception;
    void read(ChannelHandlerContext var1) throws Exception;
    void write(ChannelHandlerContext var1, Object var2, ChannelPromise var3) throws Exception;
    void flush(ChannelHandlerContext var1) throws Exception;
}

猜你喜欢
official 1032 之前的文章中提到过,单线程的nio模型任然有定缺点。在上节《netty(7)netty的线程模型》中也提到,netty的出现,封装了nio复杂的代码,并且介入多线程来事件,最大限度的提
official 1049 编码解码在网络应用中需要实现某种编解码,将原始字节数据与自定义的消息对象进行互相转换。网络中都是以字节码的数据形式来传输数据的,服务编码数据后发送到客户端,客户端需要对数据进行解码
official 1513 篇《netty(2)nio模型及多路复用》中已经简单介绍了nio模型,以及多路复用的概念,并了解nio是非阻塞的网络模型,以及与bio的区别。本篇将继续深入解nio,以及select
official 1002 个Pipeline。入栈通常是ChannelInboundHandlerAdapter的子类,主要用于读取客户端的数据。(包括数据包解码,业务逻辑等)出栈通常是ChannelO
official 783 Websocket协议http协议的关系websocket是基于TCP的个应用协议,与HTTP协议的关联之在于websocket的握手数据被HTTP服务当作HTTP包来,主要通过
official 789 什么是心跳?顾名思义,所谓心跳,即在TCP长连接中,客户端服务之间定期发送的种特殊的数据包,通知对方自己还在线,以确保TCP连接的有效性。为什么需要心跳?因为网络的不可靠性,有可能在TCP保持
official 768 。ServiceSocketChannel本身不具备数据传输的能力,它只能监听新进来的TCP链接通道。当有新的TCP链接通道建立后,它会创建个SocketChannel的对象,代表客户端的唯连接通道
official 888 在上节《netty(6)》的文章中,简要说明了用nio原生代码写程序的些不足问题,以及netty在nio的基础上大致做了那些工作。其中提到点就是当活跃客户端的数量太多,单线程时所带
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。