Netty中的ChannelHandler解析
ChannelHandler
编写Netty程序,主要业务要写在ChannelHandler处理器中。
ChannelHandler主要的类和接口如图所示:
Netty中数据的流动有入站、出站2个方向。
入站:数据从通道到InboundHandler。
出站:数据从OutboundHandler到通道。
ChannelInboundHandler的主要方法
interface ChannelInboundHandler extends ChannelHandler {
/**
* 注册通道时触发
*/
void channelRegistered(ChannelHandlerContext ctx) throws Exception;
/**
* 通道取消注册时触发
*/
void channelUnregistered(ChannelHandlerContext ctx) throws Exception;
/**
* 通道**时触发
*/
void channelActive(ChannelHandlerContext ctx) throws Exception;
/**
* 通道断开或者不可用时触发
*/
void channelInactive(ChannelHandlerContext ctx) throws Exception;
/**
* 通道可读时触发
*/
void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception;
/**
* 通道读数据完毕后触发
*/
void channelReadComplete(ChannelHandlerContext ctx) throws Exception;
/**
* 用户定义的事件被触发时
*/
void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception;
/**
* 通道的可写状态变化时触发
*/
void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception;
/**
* 通道处理过程发生异常时触发
*/
@Override
@SuppressWarnings("deprecation")
void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;
}
ChannelInboundHandlerAdapter是ChannelInboundHandler的默认实现类,实际开发中只需要extends它,重写其方法即可。
ChannelOutboundHandler接口
public interface ChannelOutboundHandler extends ChannelHandler {
/**
* 绑定ip地址端口
*/
void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception;
/**
* 连接服务端
*/
void connect(
ChannelHandlerContext ctx, SocketAddress remoteAddress,
SocketAddress localAddress, ChannelPromise promise) throws Exception;
/**
* 断开连接
*/
void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception;
/**
* 关闭通道
*/
void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception;
/**
* 取消注册EventLoop
*/
void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception;
/**
* 从底层读数据
*/
void read(ChannelHandlerContext ctx) throws Exception;
/**
* 写数据到底层
*/
void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception;
/**
* 刷新缓冲区中的数据
*/
void flush(ChannelHandlerContext ctx) throws Exception;
}
ChannelOutboundHandlerAdapter是ChannelOutboundHandler的默认实现类,实际开发中只需要extends它,重写其方法即可。
ChannelHandler的执行流程
执行流程如下几个图所示:
通过父类抽象类ChannelInitializer的 initChannel(ChannelHandlerContext ctx)方法调用abstract void initChannel(C ch)方法。
然后调用自定义的MyServerInitializer的initChannel(SocketChannel ch)方法。
ChannelInboundHandler主要方法的执行顺序是
handlerAdded
channelRegistered
channelActive
channelRead
channelReadComplete
channelInactive
channelUnregistered
handlerRemoved
SimpleChannelInboundHandler和ChannelInboundHandlerAdapter的区别
SimpleChannelInboundHandler里
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
boolean release = true;
try {
if (acceptInboundMessage(msg)) {
@SuppressWarnings("unchecked")
I imsg = (I) msg;
channelRead0(ctx, imsg);
} else {
release = false;
ctx.fireChannelRead(msg);
}
} finally {
if (autoRelease && release) {
ReferenceCountUtil.release(msg);
}
}
}
如果使用SimpleChannelInboundHandler,需要重写的是channelRead0方法,SimpleChannelInboundHandler覆写了父类的channelRead方法为我们做了释放消息的工作。如果消息ByteBuf msg的引用计数为0,会被释放。
如果使用的是ChannelInboundHandlerAdapter,ByteBuf消息只能等到writeAndFlush()方法被调用时释放。
上一篇: 老生常谈PHP中的数据结构:DS扩展
下一篇: MySQL的函数有哪些呢?快来康康吧!