Netty整理(二) 顶
- 2019 年 10 月 10 日
- 筆記
现在我们来验证一下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(); }