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(); }