• How an event flows in a pipeline Netty Internal I/O Threads (Transport Implementation)


    C:Userssas.m2 epositoryio etty etty-all4.1.30.Final etty-all-4.1.30.Final-sources.jar!io ettychannelChannelPipeline.java

    /*
    * Copyright 2012 The Netty Project
    *
    * The Netty Project licenses this file to you under the Apache License,
    * version 2.0 (the "License"); you may not use this file except in compliance
    * with the License. You may obtain a copy of the License at:
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    * License for the specific language governing permissions and limitations
    * under the License.
    */
    package io.netty.channel;

    import io.netty.buffer.ByteBuf;
    import io.netty.util.concurrent.DefaultEventExecutorGroup;
    import io.netty.util.concurrent.EventExecutorGroup;

    import java.net.SocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.SocketChannel;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.NoSuchElementException;


    /**
    * 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 class 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.
    */
    public interface ChannelPipeline
    extends ChannelInboundInvoker, ChannelOutboundInvoker, Iterable<Entry<String, ChannelHandler>> {

    /**
    * Inserts a {@link ChannelHandler} at the first position of this pipeline.
    *
    * @param name the name of the handler to insert first
    * @param handler the handler to insert first
    *
    * @throws IllegalArgumentException
    * if there's an entry with the same name already in the pipeline
    * @throws NullPointerException
    * if the specified handler is {@code null}
    */
    ChannelPipeline addFirst(String name, ChannelHandler handler);

    /**
    * Inserts a {@link ChannelHandler} at the first position of this pipeline.
    *
    * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}
    * methods
    * @param name the name of the handler to insert first
    * @param handler the handler to insert first
    *
    * @throws IllegalArgumentException
    * if there's an entry with the same name already in the pipeline
    * @throws NullPointerException
    * if the specified handler is {@code null}
    */
    ChannelPipeline addFirst(EventExecutorGroup group, String name, ChannelHandler handler);

    /**
    * Appends a {@link ChannelHandler} at the last position of this pipeline.
    *
    * @param name the name of the handler to append
    * @param handler the handler to append
    *
    * @throws IllegalArgumentException
    * if there's an entry with the same name already in the pipeline
    * @throws NullPointerException
    * if the specified handler is {@code null}
    */
    ChannelPipeline addLast(String name, ChannelHandler handler);

    /**
    * Appends a {@link ChannelHandler} at the last position of this pipeline.
    *
    * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}
    * methods
    * @param name the name of the handler to append
    * @param handler the handler to append
    *
    * @throws IllegalArgumentException
    * if there's an entry with the same name already in the pipeline
    * @throws NullPointerException
    * if the specified handler is {@code null}
    */
    ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler);

    /**
    * Inserts a {@link ChannelHandler} before an existing handler of this
    * pipeline.
    *
    * @param baseName the name of the existing handler
    * @param name the name of the handler to insert before
    * @param handler the handler to insert before
    *
    * @throws NoSuchElementException
    * if there's no such entry with the specified {@code baseName}
    * @throws IllegalArgumentException
    * if there's an entry with the same name already in the pipeline
    * @throws NullPointerException
    * if the specified baseName or handler is {@code null}
    */
    ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler);

    /**
    * Inserts a {@link ChannelHandler} before an existing handler of this
    * pipeline.
    *
    * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}
    * methods
    * @param baseName the name of the existing handler
    * @param name the name of the handler to insert before
    * @param handler the handler to insert before
    *
    * @throws NoSuchElementException
    * if there's no such entry with the specified {@code baseName}
    * @throws IllegalArgumentException
    * if there's an entry with the same name already in the pipeline
    * @throws NullPointerException
    * if the specified baseName or handler is {@code null}
    */
    ChannelPipeline addBefore(EventExecutorGroup group, String baseName, String name, ChannelHandler handler);

    /**
    * Inserts a {@link ChannelHandler} after an existing handler of this
    * pipeline.
    *
    * @param baseName the name of the existing handler
    * @param name the name of the handler to insert after
    * @param handler the handler to insert after
    *
    * @throws NoSuchElementException
    * if there's no such entry with the specified {@code baseName}
    * @throws IllegalArgumentException
    * if there's an entry with the same name already in the pipeline
    * @throws NullPointerException
    * if the specified baseName or handler is {@code null}
    */
    ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler);

    /**
    * Inserts a {@link ChannelHandler} after an existing handler of this
    * pipeline.
    *
    * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}
    * methods
    * @param baseName the name of the existing handler
    * @param name the name of the handler to insert after
    * @param handler the handler to insert after
    *
    * @throws NoSuchElementException
    * if there's no such entry with the specified {@code baseName}
    * @throws IllegalArgumentException
    * if there's an entry with the same name already in the pipeline
    * @throws NullPointerException
    * if the specified baseName or handler is {@code null}
    */
    ChannelPipeline addAfter(EventExecutorGroup group, String baseName, String name, ChannelHandler handler);

    /**
    * Inserts {@link ChannelHandler}s at the first position of this pipeline.
    *
    * @param handlers the handlers to insert first
    *
    */
    ChannelPipeline addFirst(ChannelHandler... handlers);

    /**
    * Inserts {@link ChannelHandler}s at the first position of this pipeline.
    *
    * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}s
    * methods.
    * @param handlers the handlers to insert first
    *
    */
    ChannelPipeline addFirst(EventExecutorGroup group, ChannelHandler... handlers);

    /**
    * Inserts {@link ChannelHandler}s at the last position of this pipeline.
    *
    * @param handlers the handlers to insert last
    *
    */
    ChannelPipeline addLast(ChannelHandler... handlers);

    /**
    * Inserts {@link ChannelHandler}s at the last position of this pipeline.
    *
    * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}s
    * methods.
    * @param handlers the handlers to insert last
    *
    */
    ChannelPipeline addLast(EventExecutorGroup group, ChannelHandler... handlers);

    /**
    * Removes the specified {@link ChannelHandler} from this pipeline.
    *
    * @param handler the {@link ChannelHandler} to remove
    *
    * @throws NoSuchElementException
    * if there's no such handler in this pipeline
    * @throws NullPointerException
    * if the specified handler is {@code null}
    */
    ChannelPipeline remove(ChannelHandler handler);

    /**
    * Removes the {@link ChannelHandler} with the specified name from this pipeline.
    *
    * @param name the name under which the {@link ChannelHandler} was stored.
    *
    * @return the removed handler
    *
    * @throws NoSuchElementException
    * if there's no such handler with the specified name in this pipeline
    * @throws NullPointerException
    * if the specified name is {@code null}
    */
    ChannelHandler remove(String name);

    /**
    * Removes the {@link ChannelHandler} of the specified type from this pipeline.
    *
    * @param <T> the type of the handler
    * @param handlerType the type of the handler
    *
    * @return the removed handler
    *
    * @throws NoSuchElementException
    * if there's no such handler of the specified type in this pipeline
    * @throws NullPointerException
    * if the specified handler type is {@code null}
    */
    <T extends ChannelHandler> T remove(Class<T> handlerType);

    /**
    * Removes the first {@link ChannelHandler} in this pipeline.
    *
    * @return the removed handler
    *
    * @throws NoSuchElementException
    * if this pipeline is empty
    */
    ChannelHandler removeFirst();

    /**
    * Removes the last {@link ChannelHandler} in this pipeline.
    *
    * @return the removed handler
    *
    * @throws NoSuchElementException
    * if this pipeline is empty
    */
    ChannelHandler removeLast();

    /**
    * Replaces the specified {@link ChannelHandler} with a new handler in this pipeline.
    *
    * @param oldHandler the {@link ChannelHandler} to be replaced
    * @param newName the name under which the replacement should be added
    * @param newHandler the {@link ChannelHandler} which is used as replacement
    *
    * @return itself

    * @throws NoSuchElementException
    * if the specified old handler does not exist in this pipeline
    * @throws IllegalArgumentException
    * if a handler with the specified new name already exists in this
    * pipeline, except for the handler to be replaced
    * @throws NullPointerException
    * if the specified old handler or new handler is
    * {@code null}
    */
    ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);

    /**
    * Replaces the {@link ChannelHandler} of the specified name with a new handler in this pipeline.
    *
    * @param oldName the name of the {@link ChannelHandler} to be replaced
    * @param newName the name under which the replacement should be added
    * @param newHandler the {@link ChannelHandler} which is used as replacement
    *
    * @return the removed handler
    *
    * @throws NoSuchElementException
    * if the handler with the specified old name does not exist in this pipeline
    * @throws IllegalArgumentException
    * if a handler with the specified new name already exists in this
    * pipeline, except for the handler to be replaced
    * @throws NullPointerException
    * if the specified old handler or new handler is
    * {@code null}
    */
    ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler);

    /**
    * Replaces the {@link ChannelHandler} of the specified type with a new handler in this pipeline.
    *
    * @param oldHandlerType the type of the handler to be removed
    * @param newName the name under which the replacement should be added
    * @param newHandler the {@link ChannelHandler} which is used as replacement
    *
    * @return the removed handler
    *
    * @throws NoSuchElementException
    * if the handler of the specified old handler type does not exist
    * in this pipeline
    * @throws IllegalArgumentException
    * if a handler with the specified new name already exists in this
    * pipeline, except for the handler to be replaced
    * @throws NullPointerException
    * if the specified old handler or new handler is
    * {@code null}
    */
    <T extends ChannelHandler> T replace(Class<T> oldHandlerType, String newName,
    ChannelHandler newHandler);

    /**
    * Returns the first {@link ChannelHandler} in this pipeline.
    *
    * @return the first handler. {@code null} if this pipeline is empty.
    */
    ChannelHandler first();

    /**
    * Returns the context of the first {@link ChannelHandler} in this pipeline.
    *
    * @return the context of the first handler. {@code null} if this pipeline is empty.
    */
    ChannelHandlerContext firstContext();

    /**
    * Returns the last {@link ChannelHandler} in this pipeline.
    *
    * @return the last handler. {@code null} if this pipeline is empty.
    */
    ChannelHandler last();

    /**
    * Returns the context of the last {@link ChannelHandler} in this pipeline.
    *
    * @return the context of the last handler. {@code null} if this pipeline is empty.
    */
    ChannelHandlerContext lastContext();

    /**
    * Returns the {@link ChannelHandler} with the specified name in this
    * pipeline.
    *
    * @return the handler with the specified name.
    * {@code null} if there's no such handler in this pipeline.
    */
    ChannelHandler get(String name);

    /**
    * Returns the {@link ChannelHandler} of the specified type in this
    * pipeline.
    *
    * @return the handler of the specified handler type.
    * {@code null} if there's no such handler in this pipeline.
    */
    <T extends ChannelHandler> T get(Class<T> handlerType);

    /**
    * Returns the context object of the specified {@link ChannelHandler} in
    * this pipeline.
    *
    * @return the context object of the specified handler.
    * {@code null} if there's no such handler in this pipeline.
    */
    ChannelHandlerContext context(ChannelHandler handler);

    /**
    * Returns the context object of the {@link ChannelHandler} with the
    * specified name in this pipeline.
    *
    * @return the context object of the handler with the specified name.
    * {@code null} if there's no such handler in this pipeline.
    */
    ChannelHandlerContext context(String name);

    /**
    * Returns the context object of the {@link ChannelHandler} of the
    * specified type in this pipeline.
    *
    * @return the context object of the handler of the specified type.
    * {@code null} if there's no such handler in this pipeline.
    */
    ChannelHandlerContext context(Class<? extends ChannelHandler> handlerType);

    /**
    * Returns the {@link Channel} that this pipeline is attached to.
    *
    * @return the channel. {@code null} if this pipeline is not attached yet.
    */
    Channel channel();

    /**
    * Returns the {@link List} of the handler names.
    */
    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();
    }



  • 相关阅读:
    【BZOJ1001】狼抓兔子(网络流)
    【BZOJ4554】游戏(二分图匹配,网络流)
    【BZOJ3993】星际战争(网络流,二分答案)
    【BZOJ3140】消毒(二分图匹配)
    【Luogu1393】动态逆序对(CDQ分治)
    【BZOJ3295】动态逆序对(线段树,树状数组)
    【BZOJ1305】跳舞(网络流)
    【BZOJ1934】善意的投票(网络流)
    【BZOJ3932】任务查询系统(主席树)
    【BZOJ3123】森林(主席树,启发式合并)
  • 原文地址:https://www.cnblogs.com/rsapaper/p/9951329.html
Copyright © 2020-2023  润新知