现在我们来验证一下channel的生命周期。
我们将EchoServerHandler修改如下,增加全部的监听事件,并打印事件方法名称。
/**
* 事件处理器
*/
@Slf4j
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
/**
* 监听读取事件
* @param ctx
* @param msg
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf data = (ByteBuf) msg;
log.info(data.toString(CharsetUtil.UTF_8));
ctx.writeAndFlush(data);
}
/**
* 监听读取完毕事件
* @param ctx
* @throws Exception
*/
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
log.info("channelReadComplete");
}
/**
* 监听异常事件
* @param ctx
* @param cause
* @throws Exception
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
/**
* 将channel注册到EventLoop的Selector多路复用器中
* @param ctx
* @throws Exception
*/
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
log.info("channelRegistered");
}
/**
* channel未注册到EventLoop中
* @param ctx
* @throws Exception
*/
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
log.info("channelUnregistered");
}
/**
* 有连接,变为活跃状态
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
log.info("channelActive");
}
/**
* 没有连接,非活跃状态
* @param ctx
* @throws Exception
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
log.info("channelInactive");
}
}
启动EchoServer,打开telnet连接到端口,我们可以看到
admindeMacBook-Pro:~ admin$ telnet 127.0.0.1 10101
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
sdfs
sdfs
^]
telnet> quit
Connection closed.
整个过程为连接,发送字符串sdfs,退出连接
服务端日志为
2019-10-01 05:33:36.960 INFO 543 --- ntLoopGroup-3-1 c.g.websocket.netty.EchoServerHandler : channelRegistered
2019-10-01 05:33:36.960 INFO 543 --- ntLoopGroup-3-1 c.g.websocket.netty.EchoServerHandler : channelActive
2019-10-01 05:33:54.439 INFO 543 --- ntLoopGroup-3-1 c.g.websocket.netty.EchoServerHandler : sdfs
2019-10-01 05:33:54.442 INFO 543 --- ntLoopGroup-3-1 c.g.websocket.netty.EchoServerHandler : channelReadComplete
2019-10-01 05:34:22.527 INFO 543 --- ntLoopGroup-3-1 c.g.websocket.netty.EchoServerHandler : channelReadComplete
2019-10-01 05:34:22.529 INFO 543 --- ntLoopGroup-3-1 c.g.websocket.netty.EchoServerHandler : channelInactive
2019-10-01 05:34:22.529 INFO 543 --- ntLoopGroup-3-1 c.g.websocket.netty.EchoServerHandler : channelUnregistered
整个生命周期正如前面写到一样
Channel的生命周期为:(1)channelRegistered->(3)channelActive->(4)channelInactive->(2)channelUnregistered
ChannelPipeline:
好比厂里的流水线一样,可以在上面添加多个ChannelHanler,也可看成是一串 ChannelHandler 实例,拦截穿过 Channel 的输入输出 event, ChannelPipeline 实现了拦截器的一种高级形式,使得用户可以对事件的处理以及ChannelHanler之间交互获得完全的控制权。
我们来看一下ChannelPipeline的源码
public interface ChannelPipeline
extends ChannelInboundInvoker, ChannelOutboundInvoker, Iterable<Entry<String, ChannelHandler>> {
/**
* 在管道的首位置添加一个channelhandler
*/
ChannelPipeline addFirst(String name, ChannelHandler handler);
/**
* 同上,多了一个线程池参数
*/
ChannelPipeline addFirst(EventExecutorGroup group, String name, ChannelHandler handler);
/**
* 在管道的最末端添加一个channelhandler
*/
ChannelPipeline addLast(String name, ChannelHandler handler);
/**
* 同上,多了一个线程池参数
*/
ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler);
/**
* 在一个管道中已存在的channelhandler之前插入另外一个channelhandler
*/
ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler);
/**
* 同上,多了一个线程池参数
*/
ChannelPipeline addBefore(EventExecutorGroup group, String baseName, String name, ChannelHandler handler);
/**
* 在管道已有多一个channelhandler之后插入另外一个channelhandler
*/
ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler);
/**
* 同上,多了一个线程池参数
*/
ChannelPipeline addAfter(EventExecutorGroup group, String baseName, String name, ChannelHandler handler);
/**
* 在该管道的首位置放入一组channelhandler
*
*/
ChannelPipeline addFirst(ChannelHandler... handlers);
/**
* 同上,多了一个线程池参数
*
*/
ChannelPipeline addFirst(EventExecutorGroup group, ChannelHandler... handlers);
/**
* 在管道的最末端放入一组channelhandler
*
*/
ChannelPipeline addLast(ChannelHandler... handlers);
/**
* 同上,多了一个线程池参数
*
*/
ChannelPipeline addLast(EventExecutorGroup group, ChannelHandler... handlers);
/**
* 从管道中移除一个channelhandler
*/
ChannelPipeline remove(ChannelHandler handler);
/**
* 根据名字在管道中移除一个channelhandler
*/
ChannelHandler remove(String name);
/**
* 根据类名在管道中移除一个channelhandler
*/
<T extends ChannelHandler> T remove(Class<T> handlerType);
/**
* 移除管道中首个channelhandler
*/
ChannelHandler removeFirst();
/**
* 移除管道中末个channelhandler
*/
ChannelHandler removeLast();
/**
* 在管道中用新的channelhandler替换旧的channelhandler,中间参数都是替换者的名字
*/
ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);
/**
* 在管道中用新的channelhandler替换旧的channelhandler,中间参数都是替换者的名字
*/
ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler);
/**
* 在管道中用新的channelhandler替换旧的channelhandler,中间参数都是替换者的名字
*/
<T extends ChannelHandler> T replace(Class<T> oldHandlerType, String newName,
ChannelHandler newHandler);
/**
* 返回管道中首个channelhandler
*/
ChannelHandler first();
/**
* 获取第一个管道处理器上下文
*/
ChannelHandlerContext firstContext();
/**
* 获取管道中最后一个channelhandler
*/
ChannelHandler last();
/**
* 获取管道中最后一个管道处理器上下文
*/
ChannelHandlerContext lastContext();
/**
* 根据名字获取管道中的一个channelhandler
*/
ChannelHandler get(String name);
/**
* 根据类获取一个channelhandler
*/
<T extends ChannelHandler> T get(Class<T> handlerType);
/**
* 根据channelhandler获取一个管道处理器上下文
*/
ChannelHandlerContext context(ChannelHandler handler);
/**
* 根据名字获取一个管道处理器上下文
*/
ChannelHandlerContext context(String name);
/**
* 根据一个channelhandler的类名获取一个管道处理器上下文
*/
ChannelHandlerContext context(Class<? extends ChannelHandler> handlerType);
/**
* 返回一个管道
*/
Channel channel();
/**
* 返回管道中的channelhandler的名称列表
*/
List<String> names();
/**
* Converts this pipeline into an ordered {@link Map} whose keys are
* handler names and whose values are handlers.
*/
Map<String, ChannelHandler> toMap();
@Override
ChannelPipeline fireChannelRegistered();
@Override
ChannelPipeline fireChannelUnregistered();
@Override
ChannelPipeline fireChannelActive();
@Override
ChannelPipeline fireChannelInactive();
@Override
ChannelPipeline fireExceptionCaught(Throwable cause);
@Override
ChannelPipeline fireUserEventTriggered(Object event);
@Override
ChannelPipeline fireChannelRead(Object msg);
@Override
ChannelPipeline fireChannelReadComplete();
@Override
ChannelPipeline fireChannelWritabilityChanged();
@Override
ChannelPipeline flush();
}