zoukankan      html  css  js  c++  java
  • Netty核心组件之ChannelPipeline

    /**
     * A list of {@link ChannelHandler}s which handles or intercepts inbound events and outbound operations of a
     * {@link Channel}.  {@link ChannelPipeline} implements an advanced form of the
     * <a href="http://www.oracle.com/technetwork/java/interceptingfilter-142169.html">Intercepting Filter</a> pattern
     * to give a user full control over how an event is handled and how the {@link ChannelHandler}s in a pipeline
     * interact with each other.
     *
     * <h3>Creation of a pipeline</h3>
     *
     * Each channel has its own pipeline and it is created automatically when a new channel is created.
     *
     * <h3>How an event flows in a pipeline</h3>
     *
     * The following diagram describes how I/O events are processed by {@link ChannelHandler}s in a {@link ChannelPipeline}
     * typically. An I/O event is handled by either a {@link ChannelInboundHandler} or a {@link ChannelOutboundHandler}
     * and be forwarded to its closest handler by calling the event propagation methods defined in
     * {@link ChannelHandlerContext}, such as {@link ChannelHandlerContext#fireChannelRead(Object)} and
     * {@link ChannelHandlerContext#write(Object)}.
     *
     * <pre>
     *                                                 I/O Request
     *                                            via {@link Channel} or
     *                                        {@link ChannelHandlerContext}
     *                                                      |
     *  +---------------------------------------------------+---------------+
     *  |                           ChannelPipeline         |               |
     *  |                                                  |/              |
     *  |    +---------------------+            +-----------+----------+    |
     *  |    | Inbound Handler  N  |            | Outbound Handler  1  |    |
     *  |    +----------+----------+            +-----------+----------+    |
     *  |              /|                                  |               |
     *  |               |                                  |/              |
     *  |    +----------+----------+            +-----------+----------+    |
     *  |    | Inbound Handler N-1 |            | Outbound Handler  2  |    |
     *  |    +----------+----------+            +-----------+----------+    |
     *  |              /|                                  .               |
     *  |               .                                   .               |
     *  | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|
     *  |        [ method call]                       [method call]         |
     *  |               .                                   .               |
     *  |               .                                  |/              |
     *  |    +----------+----------+            +-----------+----------+    |
     *  |    | Inbound Handler  2  |            | Outbound Handler M-1 |    |
     *  |    +----------+----------+            +-----------+----------+    |
     *  |              /|                                  |               |
     *  |               |                                  |/              |
     *  |    +----------+----------+            +-----------+----------+    |
     *  |    | Inbound Handler  1  |            | Outbound Handler  M  |    |
     *  |    +----------+----------+            +-----------+----------+    |
     *  |              /|                                  |               |
     *  +---------------+-----------------------------------+---------------+
     *                  |                                  |/
     *  +---------------+-----------------------------------+---------------+
     *  |               |                                   |               |
     *  |       [ Socket.read() ]                    [ Socket.write() ]     |
     *  |                                                                   |
     *  |  Netty Internal I/O Threads (Transport Implementation)            |
     *  +-------------------------------------------------------------------+
     * </pre>
     * An inbound event is handled by the inbound handlers in the bottom-up direction as shown on the left side of the
     * diagram.  An inbound handler usually handles the inbound data generated by the I/O thread on the bottom of the
     * diagram.  The inbound data is often read from a remote peer via the actual input operation such as
     * {@link SocketChannel#read(ByteBuffer)}.  If an inbound event goes beyond the top inbound handler, it is discarded
     * silently, or logged if it needs your attention.
     * <p>
     * An outbound event is handled by the outbound handler in the top-down direction as shown on the right side of the
     * diagram.  An outbound handler usually generates or transforms the outbound traffic such as write requests.
     * If an outbound event goes beyond the bottom outbound handler, it is handled by an I/O thread associated with the
     * {@link Channel}. The I/O thread often performs the actual output operation such as
     * {@link SocketChannel#write(ByteBuffer)}.
     * <p>
     * For example, let us assume that we created the following pipeline:
     * <pre>
     * {@link ChannelPipeline} p = ...;
     * p.addLast("1", new InboundHandlerA());
     * p.addLast("2", new InboundHandlerB());
     * p.addLast("3", new OutboundHandlerA());
     * p.addLast("4", new OutboundHandlerB());
     * p.addLast("5", new InboundOutboundHandlerX());
     * </pre>
     * In the example above, the class whose name starts with {@code Inbound} means it is an inbound handler.
     * The class whose name starts with {@code Outbound} means it is a outbound handler.
     * <p>
     * In the given example configuration, the handler evaluation order is 1, 2, 3, 4, 5 when an event goes inbound.
     * When an event goes outbound, the order is 5, 4, 3, 2, 1.  On top of this principle, {@link ChannelPipeline} skips
     * the evaluation of certain handlers to shorten the stack depth:
     * <ul>
     * <li>3 and 4 don't implement {@link ChannelInboundHandler}, and therefore the actual evaluation order of an inbound
     *     event will be: 1, 2, and 5.</li>
     * <li>1 and 2 don't implement {@link ChannelOutboundHandler}, and therefore the actual evaluation order of a
     *     outbound event will be: 5, 4, and 3.</li>
     * <li>If 5 implements both {@link ChannelInboundHandler} and {@link ChannelOutboundHandler}, the evaluation order of
     *     an inbound and a outbound event could be 125 and 543 respectively.</li>
     * </ul>
     *
     * <h3>Forwarding an event to the next handler</h3>
     *
     * As you might noticed in the diagram shows, a handler has to invoke the event propagation methods in
     * {@link ChannelHandlerContext} to forward an event to its next handler.  Those methods include:
     * <ul>
     * <li>Inbound event propagation methods:
     *     <ul>
     *     <li>{@link ChannelHandlerContext#fireChannelRegistered()}</li>
     *     <li>{@link ChannelHandlerContext#fireChannelActive()}</li>
     *     <li>{@link ChannelHandlerContext#fireChannelRead(Object)}</li>
     *     <li>{@link ChannelHandlerContext#fireChannelReadComplete()}</li>
     *     <li>{@link ChannelHandlerContext#fireExceptionCaught(Throwable)}</li>
     *     <li>{@link ChannelHandlerContext#fireUserEventTriggered(Object)}</li>
     *     <li>{@link ChannelHandlerContext#fireChannelWritabilityChanged()}</li>
     *     <li>{@link ChannelHandlerContext#fireChannelInactive()}</li>
     *     <li>{@link ChannelHandlerContext#fireChannelUnregistered()}</li>
     *     </ul>
     * </li>
     * <li>Outbound event propagation methods:
     *     <ul>
     *     <li>{@link ChannelHandlerContext#bind(SocketAddress, ChannelPromise)}</li>
     *     <li>{@link ChannelHandlerContext#connect(SocketAddress, SocketAddress, ChannelPromise)}</li>
     *     <li>{@link ChannelHandlerContext#write(Object, ChannelPromise)}</li>
     *     <li>{@link ChannelHandlerContext#flush()}</li>
     *     <li>{@link ChannelHandlerContext#read()}</li>
     *     <li>{@link ChannelHandlerContext#disconnect(ChannelPromise)}</li>
     *     <li>{@link ChannelHandlerContext#close(ChannelPromise)}</li>
     *     <li>{@link ChannelHandlerContext#deregister(ChannelPromise)}</li>
     *     </ul>
     * </li>
     * </ul>
     *
     * and the following example shows how the event propagation is usually done:
     *
     * <pre>
     * public class MyInboundHandler extends {@link ChannelInboundHandlerAdapter} {
     *     {@code @Override}
     *     public void channelActive({@link ChannelHandlerContext} ctx) {
     *         System.out.println("Connected!");
     *         ctx.fireChannelActive();
     *     }
     * }
     *
     * public clas MyOutboundHandler extends {@link ChannelOutboundHandlerAdapter} {
     *     {@code @Override}
     *     public void close({@link ChannelHandlerContext} ctx, {@link ChannelPromise} promise) {
     *         System.out.println("Closing ..");
     *         ctx.close(promise);
     *     }
     * }
     * </pre>
     *
     * <h3>Building a pipeline</h3>
     * <p>
     * A user is supposed to have one or more {@link ChannelHandler}s in a pipeline to receive I/O events (e.g. read) and
     * to request I/O operations (e.g. write and close).  For example, a typical server will have the following handlers
     * in each channel's pipeline, but your mileage may vary depending on the complexity and characteristics of the
     * protocol and business logic:
     *
     * <ol>
     * <li>Protocol Decoder - translates binary data (e.g. {@link ByteBuf}) into a Java object.</li>
     * <li>Protocol Encoder - translates a Java object into binary data.</li>
     * <li>Business Logic Handler - performs the actual business logic (e.g. database access).</li>
     * </ol>
     *
     * and it could be represented as shown in the following example:
     *
     * <pre>
     * static final {@link EventExecutorGroup} group = new {@link DefaultEventExecutorGroup}(16);
     * ...
     *
     * {@link ChannelPipeline} pipeline = ch.pipeline();
     *
     * pipeline.addLast("decoder", new MyProtocolDecoder());
     * pipeline.addLast("encoder", new MyProtocolEncoder());
     *
     * // Tell the pipeline to run MyBusinessLogicHandler's event handler methods
     * // in a different thread than an I/O thread so that the I/O thread is not blocked by
     * // a time-consuming task.
     * // If your business logic is fully asynchronous or finished very quickly, you don't
     * // need to specify a group.
     * pipeline.addLast(group, "handler", new MyBusinessLogicHandler());
     * </pre>
     *
     * <h3>Thread safety</h3>
     * <p>
     * A {@link ChannelHandler} can be added or removed at any time because a {@link ChannelPipeline} is thread safe.
     * For example, you can insert an encryption handler when sensitive information is about to be exchanged, and remove it
     * after the exchange.
     */
  • 相关阅读:
    如何使用Win32API绘制树
    MSD_radix_sort
    Radix Sort
    Computer Science: the Big Picture
    天问之Linux内核中的不明白的地方
    viewController备注
    loadView、viewDidLoad及viewDidUnload的关系(转)
    iOS 中的视图函数 init initwithnib viewDidLoad viewWillAppear的总结
    做ios工程时,把UI从xib移动到代码中遇到的问题
    嘟嘟三期的所学所想
  • 原文地址:https://www.cnblogs.com/mmh760/p/14081842.html
Copyright © 2011-2022 走看看