Netty之ChannelHandler(三)

本文深入探讨Netty中的ChannelHandler机制,包括Channel接口、Channel生命周期、ChannelHandler及其子接口的功能与实现细节,同时解析ChannelHandlerContext的作用及组件间的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ChannelHandler是netty中的核心处理部分,我们使用netty的绝大部分代码都写在这部分,所以了解它的一些机制和特性是很有必要的。

一、Channel

Channel接口抽象了底层socket的一些状态属性以及调用方法

针对不同类型的socket提供不同的子类实现。

二、Channel生命周期

三、ChannelHandler

ChannelHandler用于处理Channel对应的事件
ChannelHandler接口里面只定义了三个生命周期方法,我们主要实现它的子接口ChannelInboundHandler和ChannelOutboundHandler,为了便利,框架提供了ChannelInboundHandlerAdapter,ChannelOutboundHandlerAdapter和ChannelDuplexHandler这三个适配类,在使用的时候只需要实现你关注的方法即可

ChannelHandler生命周期方法:

ChannelHandler里面定义三个生命周期方法,分别会在当前ChannelHander加入ChannelHandlerContext中,从ChannelHandlerContext中移除,以及ChannelHandler回调方法出现异常时被回调。

四、ChannelInboundHandler 和 ChannelOutboundHandler

1. ChannelInBoundHandler

介绍一下这些回调方法被触发的时机:

回调方法   触发时机client    server    
channelRegistered当前channel注册到EventLooptruetrue
channelUnregistered当前channel从EventLoop取消注册truetrue
channelActive当前channel激活的时候truetrue
channelInactive当前channel不活跃的时候,也就是当前channel到了它生命周期尾truetrue
channelRead当前channel从远端读取到数据truetrue
channelReadCompletechannel read消费完读取的数据的时候被触发truetrue
userEventTriggered用户事件触发的时候
channelWritabilityChangedchannel的写状态变化的时候触发

可以注意到每个方法都带了ChannelHandlerContext作为参数,具体作用是,在每个回调事件里面,处理完成之后,使用ChannelHandlerContext的fireChannelXXX方法来传递给下个ChannelHandler,netty的codec模块和业务处理代码分离就用到了这个链路处理。

2. ChannelOutboundHandler

回调方法   触发时机   client  server   
bindbind操作执行前触发falsetrue
connectconnect 操作执行前触发truefalse
disconnectdisconnect 操作执行前触发truefalse
closeclose操作执行前触发falsetrue
deregisterderegister操作执行前触发
readread操作执行前触发truetrue
writewrite操作执行前触发truetrue
flushflush操作执行前触发truetrue

注意到一些回调方法有ChannelPromise这个参数,我们可以调用它的addListener注册监听,当回调方法所对应的操作完成后,会触发这个监听。

下面这个代码,会在写操作完成后触发,完成操作包括成功和失败:

public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
    ctx.write(msg,promise);
    System.out.println("out write");
    promise.addListener(new GenericFutureListener<Future<? super Void>>() {
        @Override
        public void operationComplete(Future<? super Void> future) throws Exception {
            if(future.isSuccess()){
                System.out.println("OK");
            }
        }
    });
}

3. ChannelInBoundHandler 和 ChannelOutboundHandler的区别

个人感觉in和out的区别主要在于ChannelInboundHandler的channelRead和channelReadComplete回调和ChannelOutboundHandler的write和flush回调上,ChannelOutboundHandler的channelRead回调负责执行入栈数据的decode逻辑,ChannelOutboundHandler的write负责执行出站数据的encode工作。其他回调方法和具体触发逻辑有关,和in与out无关。

五、ChannelHandlerContext

每个ChannelHandler通过add方法加入到ChannelPipeline中去的时候,会创建一个对应的ChannelHandlerContext,并且绑定,ChannelPipeline实际维护的是ChannelHandlerContext 的关系。
在DefaultChannelPipeline源码中可以看到会保存第一个ChannelHandlerContext以及最后一个ChannelHandlerContext的引用。

六、总结

上述组件的关系:

  1. 每个Channel会绑定一个ChannelPipeline,ChannelPipeline中也会持有Channel的引用
  2. ChannelPipeline持有ChannelHandlerContext链路,保留ChannelHandlerContext的头尾节点指针
  3. 每个ChannelHandlerContext会对应一个ChannelHandler,也就相当于ChannelPipeline持有ChannelHandler链路
  4. ChannelHandlerContext同时也会持有ChannelPipeline引用,也就相当于持有Channel引用
  5. ChannelHandler链路会根据Handler的类型,分为InBound和OutBound两条链路

 

转载于:https://www.cnblogs.com/myitnews/p/11440908.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值