netty4.0.x源码分析—ChannelPipeline

转载 2015年07月07日 16:47:06

备注:本文的分析基于netty 4.0.9final版本

1、ChannelPipeline结构图


2、关键类和接口分析

上一篇关于Channel的文章,在AbstractChannel的介绍中,以及提到了pipeline,这是操作处理的入口,是一个比较重要的概念,这里有必要对pipeline分析一下。

1)ChannelInboundInvoker

  1. /** 
  2.  * Interface which is shared by others which need to fire inbound events 
  3.  */  
  4. interface ChannelInboundInvoker {  
  5.   
  6.     /** 
  7.      * A {@link Channel} was registered to its {@link EventLoop}. 
  8.      * 
  9.      * This will result in having the  {@link ChannelInboundHandler#channelRegistered(ChannelHandlerContext)} method 
  10.      * called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the 
  11.      * {@link Channel}. 
  12.      */  
  13.     ChannelInboundInvoker fireChannelRegistered();  
  14.   
  15.     /** 
  16.      * A {@link Channel} was unregistered from its {@link EventLoop}. 
  17.      * 
  18.      * This will result in having the  {@link ChannelInboundHandler#channelUnregistered(ChannelHandlerContext)} method 
  19.      * called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the 
  20.      * {@link Channel}. 
  21.      */  
  22.     @Deprecated  
  23.     ChannelInboundInvoker fireChannelUnregistered();  
  24.   
  25.     /** 
  26.      * A {@link Channel} is active now, which means it is connected. 
  27.      * 
  28.      * This will result in having the  {@link ChannelInboundHandler#channelActive(ChannelHandlerContext)} method 
  29.      * called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the 
  30.      * {@link Channel}. 
  31.      */  
  32.     ChannelInboundInvoker fireChannelActive();  
  33.   
  34.     /** 
  35.      * A {@link Channel} is inactive now, which means it is closed. 
  36.      * 
  37.      * This will result in having the  {@link ChannelInboundHandler#channelInactive(ChannelHandlerContext)} method 
  38.      * called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the 
  39.      * {@link Channel}. 
  40.      */  
  41.     ChannelInboundInvoker fireChannelInactive();  
  42.   
  43.     /** 
  44.      * A {@link Channel} received an {@link Throwable} in one of its inbound operations. 
  45.      * 
  46.      * This will result in having the  {@link ChannelInboundHandler#exceptionCaught(ChannelHandlerContext, Throwable)} 
  47.      * method  called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the 
  48.      * {@link Channel}. 
  49.      */  
  50.     ChannelInboundInvoker fireExceptionCaught(Throwable cause);  
  51.   
  52.     /** 
  53.      * A {@link Channel} received an user defined event. 
  54.      * 
  55.      * This will result in having the  {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)} 
  56.      * method  called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the 
  57.      * {@link Channel}. 
  58.      */  
  59.     ChannelInboundInvoker fireUserEventTriggered(Object event);  
  60.   
  61.     /** 
  62.      * A {@link Channel} received a message. 
  63.      * 
  64.      * This will result in having the {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} 
  65.      * method  called of the next {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the 
  66.      * {@link Channel}. 
  67.      */  
  68.     ChannelInboundInvoker fireChannelRead(Object msg);  
  69.   
  70.     ChannelInboundInvoker fireChannelReadComplete();  
  71.   
  72.     /** 
  73.      * Triggers an {@link ChannelInboundHandler#channelWritabilityChanged(ChannelHandlerContext)} 
  74.      * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. 
  75.      */  
  76.     ChannelInboundInvoker fireChannelWritabilityChanged();  
  77. }  
这接口定义比较简单,即有事件数据从底层到应用时,用它来做相应的处理。

2)ChannelOutboundInvoker

  1. /** 
  2.  * Interface which is shared by others which need to execute outbound logic. 
  3.  */  
  4. interface ChannelOutboundInvoker {  
  5.   
  6.     /** 
  7.      * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation 
  8.      * completes, either because the operation was successful or because of an error. 
  9.      * <p> 
  10.      * This will result in having the 
  11.      * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method 
  12.      * called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the 
  13.      * {@link Channel}. 
  14.      */  
  15.     ChannelFuture bind(SocketAddress localAddress);  
  16.   
  17.     /** 
  18.      * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation 
  19.      * completes, either because the operation was successful or because of an error. 
  20.      * <p> 
  21.      * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with 
  22.      * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} 
  23.      * will be used. 
  24.      * <p> 
  25.      * This will result in having the 
  26.      * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} 
  27.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the 
  28.      * {@link Channel}. 
  29.      */  
  30.     ChannelFuture connect(SocketAddress remoteAddress);  
  31.   
  32.     /** 
  33.      * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the 
  34.      * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of 
  35.      * an error. 
  36.      * <p> 
  37.      * This will result in having the 
  38.      * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} 
  39.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the 
  40.      * {@link Channel}. 
  41.      */  
  42.     ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress);  
  43.   
  44.     /** 
  45.      * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, 
  46.      * either because the operation was successful or because of an error. 
  47.      * <p> 
  48.      * This will result in having the 
  49.      * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} 
  50.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the 
  51.      * {@link Channel}. 
  52.      */  
  53.     ChannelFuture disconnect();  
  54.   
  55.     /** 
  56.      * Request to close this ChannelOutboundInvoker and notify the {@link ChannelFuture} once the operation completes, 
  57.      * either because the operation was successful or because of 
  58.      * an error. 
  59.      * 
  60.      * After it is closed it is not possible to reuse it again. 
  61.      * <p> 
  62.      * This will result in having the 
  63.      * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} 
  64.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the 
  65.      * {@link Channel}. 
  66.      */  
  67.     ChannelFuture close();  
  68.   
  69.     /** 
  70.      * Request to deregister this ChannelOutboundInvoker from the previous assigned {@link EventExecutor} and notify the 
  71.      * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of 
  72.      * an error. 
  73.      * <p> 
  74.      * This will result in having the 
  75.      * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} 
  76.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the 
  77.      * {@link Channel}. 
  78.      * 
  79.      */  
  80.     @Deprecated  
  81.     ChannelFuture deregister();  
  82.   
  83.     /** 
  84.      * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation 
  85.      * completes, either because the operation was successful or because of an error. 
  86.      * 
  87.      * The given {@link ChannelPromise} will be notified. 
  88.      * <p> 
  89.      * This will result in having the 
  90.      * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method 
  91.      * called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the 
  92.      * {@link Channel}. 
  93.      */  
  94.     ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise);  
  95.   
  96.     /** 
  97.      * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation 
  98.      * completes, either because the operation was successful or because of an error. 
  99.      * 
  100.      * The given {@link ChannelFuture} will be notified. 
  101.      * 
  102.      * <p> 
  103.      * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with 
  104.      * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} 
  105.      * will be used. 
  106.      * <p> 
  107.      * This will result in having the 
  108.      * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} 
  109.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the 
  110.      * {@link Channel}. 
  111.      */  
  112.     ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise);  
  113.   
  114.     /** 
  115.      * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the 
  116.      * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of 
  117.      * an error. 
  118.      * 
  119.      * The given {@link ChannelPromise} will be notified and also returned. 
  120.      * <p> 
  121.      * This will result in having the 
  122.      * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} 
  123.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the 
  124.      * {@link Channel}. 
  125.      */  
  126.     ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);  
  127.   
  128.     /** 
  129.      * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, 
  130.      * either because the operation was successful or because of an error. 
  131.      * 
  132.      * The given {@link ChannelPromise} will be notified. 
  133.      * <p> 
  134.      * This will result in having the 
  135.      * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} 
  136.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the 
  137.      * {@link Channel}. 
  138.      */  
  139.     ChannelFuture disconnect(ChannelPromise promise);  
  140.   
  141.     /** 
  142.      * Request to close this ChannelOutboundInvoker and notify the {@link ChannelFuture} once the operation completes, 
  143.      * either because the operation was successful or because of 
  144.      * an error. 
  145.      * 
  146.      * After it is closed it is not possible to reuse it again. 
  147.      * The given {@link ChannelPromise} will be notified. 
  148.      * <p> 
  149.      * This will result in having the 
  150.      * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} 
  151.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the 
  152.      * {@link Channel}. 
  153.      */  
  154.     ChannelFuture close(ChannelPromise promise);  
  155.   
  156.     /** 
  157.      * Request to deregister this ChannelOutboundInvoker from the previous assigned {@link EventExecutor} and notify the 
  158.      * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of 
  159.      * an error. 
  160.      * 
  161.      * The given {@link ChannelPromise} will be notified. 
  162.      * <p> 
  163.      * This will result in having the 
  164.      * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} 
  165.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the 
  166.      * {@link Channel}. 
  167.      */  
  168.     @Deprecated  
  169.     ChannelFuture deregister(ChannelPromise promise);  
  170.   
  171.     /** 
  172.      * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an 
  173.      * {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} event if data was 
  174.      * read, and triggers a 
  175.      * {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext) channelReadComplete} event so the 
  176.      * handler can decide to continue reading.  If there's a pending read operation already, this method does nothing. 
  177.      * <p> 
  178.      * This will result in having the 
  179.      * {@link ChannelOutboundHandler#read(ChannelHandlerContext)} 
  180.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the 
  181.      * {@link Channel}. 
  182.      */  
  183.     ChannelOutboundInvoker read();  
  184.   
  185.     /** 
  186.      * Request to write a message via this ChannelOutboundInvoker through the {@link ChannelPipeline}. 
  187.      * This method will not request to actual flush, so be sure to call {@link #flush()} 
  188.      * once you want to request to flush all pending data to the actual transport. 
  189.      */  
  190.     ChannelFuture write(Object msg);  
  191.   
  192.     /** 
  193.      * Request to write a message via this ChannelOutboundInvoker through the {@link ChannelPipeline}. 
  194.      * This method will not request to actual flush, so be sure to call {@link #flush()} 
  195.      * once you want to request to flush all pending data to the actual transport. 
  196.      */  
  197.     ChannelFuture write(Object msg, ChannelPromise promise);  
  198.   
  199.     /** 
  200.      * Request to flush all pending messages via this ChannelOutboundInvoker. 
  201.      */  
  202.     ChannelOutboundInvoker flush();  
  203.   
  204.     /** 
  205.      * Shortcut for call {@link #write(Object, ChannelPromise)} and {@link #flush()}. 
  206.      */  
  207.     ChannelFuture writeAndFlush(Object msg, ChannelPromise promise);  
  208.   
  209.     /** 
  210.      * Shortcut for call {@link #write(Object)} and {@link #flush()}. 
  211.      */  
  212.     ChannelFuture writeAndFlush(Object msg);  
  213. }  
这个接口定义用于处理从应用到底层的事件数据。

3)ChannelPipeline

ChannelPipeline继承ChannelInboundInvoker和ChannelOutboundInvoker,它既是一个inboundinvoke,又是一个outboundinvoke,同时它也是ChannelHandler的管理者,提供了很多方法对handler进行操作。


4)DefaultChannelPipeline

在分析DefaultChannelPipeline之前,不得不先分析DefaultChannelHandlerContext(实现ChannelHandlerContext),因为ChannelPipeline的所有handler执行都是间接由ChannelhandlerContext执行的,在后面DefaultChannelPipeline的定义中,我们可以看到这点。

ChannelHandlerContext接口定义了很多方法,关键代码如下:

  1. /** 
  2.  * Return the {@link Channel} which is bound to the {@link ChannelHandlerContext}. 
  3.  */  
  4. Channel channel();  
  5.   
  6. /** 
  7.  * The {@link EventExecutor} that is used to dispatch the events. This can also be used to directly 
  8.  * submit tasks that get executed in the event loop. For more information please refer to the 
  9.  * {@link EventExecutor} javadoc. 
  10.  */  
  11. EventExecutor executor();  
返回当前HandlerContext的Channel,以及返回当前EventExcutor。


DefaultChannelHandlerContext具体的final类,关键代码如下:

  1. volatile DefaultChannelHandlerContext next;  
  2. volatile DefaultChannelHandlerContext prev;  
  3.   
  4. private final boolean inbound;  
  5. private final boolean outbound;  
  6. private final AbstractChannel channel;  
  7. private final DefaultChannelPipeline pipeline;  
  8. private final String name;  
  9. private final ChannelHandler handler;  
  10. private boolean removed;  
  11.   
  12. // Will be set to null if no child executor should be used, otherwise it will be set to the  
  13. // child executor.  
  14. final EventExecutor executor;  
  15. private ChannelFuture succeededFuture;  
从上述代码中可以看出,DefaultChannelHandlerContext其实是一个上下文环境,它里面包括了当前Channel,当前的pipeline,以及当前的handler。另外它还提供了很多方法的实现,列如下面的函数。
  1. @Override  
  2. public ChannelHandlerContext fireChannelActive() {  
  3.     final DefaultChannelHandlerContext next = findContextInbound();  
  4.     EventExecutor executor = next.executor();  
  5.     if (executor.inEventLoop()) {  
  6.         next.invokeChannelActive();  
  7.     } else {  
  8.         executor.execute(new Runnable() {  
  9.             @Override  
  10.             public void run() {  
  11.                 next.invokeChannelActive();  
  12.             }  
  13.         });  
  14.     }  
  15.     return this;  
  16. }  
从这个函数中,可以看出Handler的执行是由executor以线程的方式执行的。


分析完DefaultChannelHandlerContext,下面再来看DefaultChannelPipeline(实现Channelpipeline)。它是一个具体的handler管理者,handler的类型可以是inboundhandler,也可以是outboundhandler。关键代码如下:

  1. final AbstractChannel channel;  
  2.   
  3. final DefaultChannelHandlerContext head;  
  4. final DefaultChannelHandlerContext tail;  
  5.   
  6. private final Map<String, DefaultChannelHandlerContext> name2ctx =  
  7.     new HashMap<String, DefaultChannelHandlerContext>(4);  
  8.   
  9. final Map<EventExecutorGroup, EventExecutor> childExecutors =  
  10.         new IdentityHashMap<EventExecutorGroup, EventExecutor>();  
  11.   
  12. public DefaultChannelPipeline(AbstractChannel channel) {  
  13.     if (channel == null) {  
  14.         throw new NullPointerException("channel");  
  15.     }  
  16.     this.channel = channel;  
  17.   
  18.     TailHandler tailHandler = new TailHandler();  
  19.     tail = new DefaultChannelHandlerContext(thisnull, generateName(tailHandler), tailHandler);  
  20.   
  21.     HeadHandler headHandler = new HeadHandler(channel.unsafe());  
  22.     head = new DefaultChannelHandlerContext(thisnull, generateName(headHandler), headHandler);  
  23.   
  24.     head.next = tail;  
  25.     tail.prev = head;  
  26. }  

从上述代码中可以看出,每个Channel都有一个对应的pipeline,每个pipeline有两个ChannelHandlerContext,分别包含默认的TailHandler和HeadHandler,并且它们构成一个双向链表结构。TailHandler处理inbound类型的数据;HeadHandler处理outbound类型的数据。


TailHandler是一个内部类,它实现ChannelInboundHandler接口,定义如下:

  1. // A special catch-all handler that handles both bytes and messages.  
  2. static final class TailHandler implements ChannelInboundHandler {  
  3.   
  4.     @Override  
  5.     public void channelRegistered(ChannelHandlerContext ctx) throws Exception { }  
  6.   
  7.     @Override  
  8.     public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { }  
  9.   
  10.     @Override  
  11.     public void channelActive(ChannelHandlerContext ctx) throws Exception { }  
  12.   
  13.     @Override  
  14.     public void channelInactive(ChannelHandlerContext ctx) throws Exception { }  
  15.   
  16.     @Override  
  17.     public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { }  
  18.   
  19.     @Override  
  20.     public void handlerAdded(ChannelHandlerContext ctx) throws Exception { }  
  21.   
  22.     @Override  
  23.     public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { }  
  24.   
  25.     @Override  
  26.     public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { }  
  27.   
  28.     @Override  
  29.     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {  
  30.         logger.warn(  
  31.                 "An exceptionCaught() event was fired, and it reached at the tail of the pipeline. " +  
  32.                         "It usually means the last handler in the pipeline did not handle the exception.", cause);  
  33.     }  
  34.   
  35.     @Override  
  36.     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {  
  37.         try {  
  38.             logger.debug(  
  39.                     "Discarded inbound message {} that reached at the tail of the pipeline. " +  
  40.                             "Please check your pipeline configuration.", msg);  
  41.         } finally {  
  42.             ReferenceCountUtil.release(msg);  
  43.         }  
  44.     }  
  45.   
  46.     @Override  
  47.     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { }  
  48. }  
TailHandler的实现函数都是空的,这说明对于底层上来应用的数据,用户必须定义Handler来处理,不能使用默认的Handler进行处理。


HeadHandler也是一个内部类,它实现ChannelOutboundHandler接口,定义如下:

  1. static final class HeadHandler implements ChannelOutboundHandler {  
  2.   
  3.     protected final Unsafe unsafe;  
  4.   
  5.     protected HeadHandler(Unsafe unsafe) {  
  6.         this.unsafe = unsafe;  
  7.     }  
  8.   
  9.     @Override  
  10.     public void handlerAdded(ChannelHandlerContext ctx) throws Exception {  
  11.         // NOOP  
  12.     }  
  13.   
  14.     @Override  
  15.     public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {  
  16.         // NOOP  
  17.     }  
  18.   
  19.     @Override  
  20.     public void bind(  
  21.             ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise)  
  22.             throws Exception {  
  23.         unsafe.bind(localAddress, promise);  
  24.     }  
  25.   
  26.     @Override  
  27.     public void connect(  
  28.             ChannelHandlerContext ctx,  
  29.             SocketAddress remoteAddress, SocketAddress localAddress,  
  30.             ChannelPromise promise) throws Exception {  
  31.         unsafe.connect(remoteAddress, localAddress, promise);  
  32.     }  
  33.   
  34.     @Override  
  35.     public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {  
  36.         unsafe.disconnect(promise);  
  37.     }  
  38.   
  39.     @Override  
  40.     public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {  
  41.         unsafe.close(promise);  
  42.     }  
  43.   
  44.     @Override  
  45.     public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {  
  46.         unsafe.deregister(promise);  
  47.     }  
  48.   
  49.     @Override  
  50.     public void read(ChannelHandlerContext ctx) {  
  51.         unsafe.beginRead();  
  52.     }  
  53.   
  54.     @Override  
  55.     public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {  
  56.         unsafe.write(msg, promise);  
  57.     }  
  58.   
  59.     @Override  
  60.     public void flush(ChannelHandlerContext ctx) throws Exception {  
  61.         unsafe.flush();  
  62.     }  
  63.   
  64.     @Override  
  65.     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {  
  66.         ctx.fireExceptionCaught(cause);  
  67.     }  
  68. }  
HeaderHandler的实现函数都是基于unsafe对象的函数实现的,所以对于OutBound类型的数据,即应用往底层的数据,可以使用默认的Handler进行处理。


3、基于DefaultChannelPipeline的fireChannelActive函数分析handler的调用过程

1)fireChannelActive定义

  1. @Override  
  2. public ChannelPipeline fireChannelActive() {  
  3.     head.fireChannelActive();  
  4.   
  5.     if (channel.config().isAutoRead()) {  
  6.         channel.read();  
  7.     }  
  8.   
  9.     return this;  
  10. }  

2) fireChannelActive实现分析
  1. @Override  
  2. public ChannelHandlerContext fireChannelActive() {  
  3.     final DefaultChannelHandlerContext next = findContextInbound();  
  4.     EventExecutor executor = next.executor();  
  5.     if (executor.inEventLoop()) {  
  6.         next.invokeChannelActive();  
  7.     } else {  
  8.         executor.execute(new Runnable() {  
  9.             @Override  
  10.             public void run() {  
  11.                 next.invokeChannelActive();  
  12.             }  
  13.         });  
  14.     }  
  15.     return this;  
  16. }<pre name="code" class="java">    private DefaultChannelHandlerContext findContextInbound() {  
  17.     DefaultChannelHandlerContext ctx = this;  
  18.     do {  
  19.         ctx = ctx.next;  
  20.     } while (!ctx.inbound);  
  21.     return ctx;  
  22. }  
  1. private void invokeChannelActive() {  
  2.     try {  
  3.         ((ChannelInboundHandler) handler).channelActive(this);  
  4.     } catch (Throwable t) {  
  5.         notifyHandlerException(t);  
  6.     }  
  7. }  

上面的代码逻辑还是比较简单的,就是从Channelhandlercontext的Head链表中获取上下文,然后调用相应的Handler执行函数。作为开发者,这时必须定义自己的Handler,并且实现ChannelActive函数,因为这是从底层到应用的数据,这就是平时我们在编写服务器端的代码时,都会定义一个继承InboundHandler的handler,并且覆盖channelActive函数的原因。

4、总结

本文分析了ChannelPipeline对Handler的管理过程,它的主要思路是利用ChannelHandlerContext上下文获取Handler,然后间接调用Handler的函数实现处理逻辑。

相关文章推荐

netty4.0.x源码分析—event

备注:本文的分析基于netty4.0.9final版本 1、event总体结构图 event总体结构类图如下: 2、event关键类和接口分析 1)基于NioEventLoop对关键类和接口进...

[netty核心类]--ChannelPipeline和ChannelHandler源码分析

本文主要包括: (1)ChannelPipeline的功能说明和源码分析; (2)ChannelHandler的功能说明和源码分析; 在netty中的ChannelPipeline和Cha...

Netty3 源码分析 - ChannelPipeline

ChannelPipeline的作用就是组织一系列的ChannelHandlers 为某一个Channel服务,处理各种事件。实现了拦截过滤器模式的高级形式(an advanced form of t...

Netty源码学习——ChannelPipeline模型分析

参考Netty API io.netty.channel.ChannelPipeline A list of ChannelHandlers which handles or intercepts...

[netty源码分析]--ChannelPipeline源码分析(一)

在前面我们已经分析过了netty的线程模型,了解了当线程池启动之后就会处于一种事件循环的状态,不断调用select() 函数,查询已注册的channel中的就绪事件。 下面我们就来研究一下当IO事件被...

【Netty源码学习】ChannelPipeline(一)

ChannelPipeline类似于一个管道,管道中存放的是一系列对读取数据进行业务操作的ChannelHandler。1、ChannelPipeline的结构图:在之前的博客【Netty源码学习】入...

【Netty源码】ChannelPipeline源码剖析

1.图解 每个channel内部都会持有一个ChannelPipeline对象pipeline. pipeline默认实现DefaultChannelPipeline内部维护了一个DefaultCh...

netty5笔记-总体流程分析2-ChannelPipeline

上一篇文章中,我们介绍了ServerBootstrap的启动过程,在这个过程中引出了一个很重要的类ChannelPipeline。如果说内存池,线程模型是netty的基础,我们接触的相对来说并不是那么...

Android 4.0 Launcher2源码分析—桌面快捷图标的拖拽

Android 4.0 Launcher2源码分析—桌面快捷图标的拖拽 (2013-06-15 20:07:54) 标签: it   http:...

Android4.0.x 源码下载,模拟器编译和运行

经过漫长的等待, android4.0 (Ice Cream Sandwich)的源码终于放出来了 (三星说,嘿嘿,我的产品已经开卖了好几个星期了,不要意思,又领先了一步),本博客将在第一时间与大家分...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:netty4.0.x源码分析—ChannelPipeline
举报原因:
原因补充:

(最多只允许输入30个字)