Netty整理(二) 頂

  • 2019 年 10 月 10 日
  • 筆記

Netty整理

現在我們來驗證一下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();  }