如果有什么不懂可以看看前面的几篇文章,我们发现它其实生成了一个Channel类型的ChannelFuture那么这个类是干什么的呢?我们看看DOc
/**
* A nexus to a network socket or a component which is capable of I/O
* operations such as read, write, connect, and bind.
* (channel 可以认为是一个连接点 , 网络套接制的一个组件,channel对于网络Socket的一个连接组件, 是可以进行IO操作的,读,写,绑定)
*
* A channel provides a user:
*
* - the current state of the channel (e.g. is it open? is it connected?),
* (获取到当前的状态,比如说 是不是打开,是否链接上)
* - the {@linkplain ChannelConfig configuration parameters} of the channel (e.g. receive buffer size),
* (通过以一些配置参数来实现的,提供了一些配置参数,比如说Buffer的大小)
* - the I/O operations that the channel supports (e.g. read, write, connect, and bind), and
* (提供对当前连接的IO操作,比如说,读,写, 连接,绑定)
* - the {@link ChannelPipeline} which handles all I/O events and requests
* associated with the channel.
*(Channel可以向用户提供ChannelPipeline(channel的管道),是可以处理与当前channel事件所关联的操作与请求所有IO操作 与请求)
* 也就是说我们这个Channel连接上之后,所有的Channel连接的请求,都可以通过这个ChannelPipeline组件获取到 ChannelPipeline 是将所有的Event_handle() 来有机的组合起来,使得组合之后生成一个链条
*
* 问题 ChannelPipeline是在什么时期创建的呢?
*
*
* All I/O operations are asynchronous.
* 所有的IO操作都是异步的
* All I/O operations in Netty are asynchronous. It means any I/O calls will
* return immediately with no guarantee that the requested I/O operation has
* been completed at the end of the call.
* 这意味着任何I / O调用将立即返回,并且不保证在调用结束时已完成所请求的I / O操作。
* Instead, you will be returned with
* a {@link ChannelFuture} instance which will notify you when the requested I/O
* operation has succeeded, failed, or canceled.
* 将返回一个ChannelFuture 来告诉你是否成功了,失败了,或者其他
*
Channels are hierarchical(可继承的)
*
* A {@link Channel} can have a {@linkplain #parent() parent} depending on
* how it was created. For instance, a {@link SocketChannel}, that was accepted
* by {@link ServerSocketChannel}, will return the {@link ServerSocketChannel}
* as its parent on {@link #parent()}.
*
* 一个Channel可以拥有一个parent(),这取决于这个Channel的创建方式,比如说:一个SocketChannel是由ServerSocketChannel()创建的
*
* The semantics of the hierarchical structure depends on the transport
* implementation where the {@link Channel} belongs to.
* 层次化的语意取决于Channel的实现,
* For example, you could
* write a new {@link Channel} implementation that creates the sub-channels that
* share one socket connection, as BEEP and
* SSH do.
*大概意思就是说你可以编写一个新的Channel并且实现其接口,这个字Channel就可以共享它的连接,与数据等数据 如同SHH 协议一样
*
Downcast to access transport-specific operations
*
* Some transports exposes additional operations that is specific to the
* transport. Down-cast the {@link Channel} to sub-type to invoke such
* operations. For example, with the old I/O datagram transport, multicast
* join / leave operations are provided by {@link DatagramChannel}.
*同样的因为层次化的结构,也可以进行向下转化,可以访问实现类的一些方法
*
Release resources
*
* It is important to call {@link #close()} or {@link #close(ChannelPromise)} to release all
* resources once you are done with the {@link Channel}. This ensures all resources are
* released in a proper way, i.e. filehandles.
1 是一个连接点2所有的请求都是异步的
*/
这是Channel里面相关的文档,以及本人理解的一些翻译,然后里面是一些相关的方法.那么它里面的ChannelPipeline看似是一个非常重要的方法.作用我在Doc里面做了理解是
上面的gif 表示的是 bind 方法的源码追踪 我们看看重点关注一下 init() 这个方法,也就是它的初始化方法
我们到 下面这段代码的用法以及注释 我们看到其实这个channel是直接使用它的 并且下面的方法也是直接想其添加 相关的Channel 也就是说在使用它的时候已经创建好了
//获取到pipeline
// 我们看后文看到p 直接被使用 那么到底是什么时候创建的呢 ? 是不是在创建Channel的时候 pipeline是不是已经创建好了呢 ?
// 生成父类的时候会对Channel对象进行初始化
//创建好并返回
ChannelPipeline p = channel.pipeline();
好我们在往下跟看看有没有什么发现 :
我们追到了DefaultChannelPipeline里面同时 我们在AbstractChannel 这个类的构造方法里面发现它的赋值过程
protected AbstractChannel(Channel parent) {
this.parent = parent;
id = newId();
unsafe = newUnsafe();
pipeline = newChannelPipeline(); //直接通过构造函数赋值的这个pipeline值的
}
同时看一下他的构造方法:
protected DefaultChannelPipeline(Channel channel) {
this.channel = ObjectUtil.checkNotNull(channel, "channel");
succeededFuture = new SucceededChannelFuture(channel, null);
voidPromise = new VoidChannelPromise(channel, true);
//尾巴 tail上下文的信息 ,并且是链表的操作
tail = new TailContext(this);
//一个头
head = new HeadContext(this);
//通过链表的方式结合起来 保证顺序
head.next = tail;
tail.prev = head;
}
关于更详细的内容我们可以参考这里做更深的理解
我们来看看它的具体ChannelPipeline里面具体的参数以及说明(用我蹩脚的英文,以及其他参考资料的理解)直接上Doc
**
* 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.
* 1是一个ChannelHandler 的列表,2本来就是一个handles 的集合会处理或者拦截进和出的操作,
* 3实现了拦截过滤器的模式 给用户完全的控制,如何处理一个事件以及管道当中的handle是如何的交互的方式
* 可以控制Channel
*
* <h3>Creation of a pipeline</h3>
*
* Each channel has its own pipeline and it is created automatically when a new channel is created.
* 每一个channel都有自己一个的pipeline 对象 ,在创建channel同时 创建该对象的
*
* <h3>How an event flows in a pipeline</h3>
* 事件是如何在pipeline 当中流动的 ?
* The following diagram describes how I/O events are processed by {@link ChannelHandler}s in a {@link ChannelPipeline}
* 下面是描述 IO事件是如何ChannelPipeline当中若干个ChannelHandler 处理的?
* typically. An I/O event is handled by either a {@link ChannelInboundHandler} or a {@link ChannelOutboundHandler}
* 所有的IO事件,要么是被ChannelInboundHandler 处理或者 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)}.
* 转发给与之最近的Handler 处理 ,是调用 ChannelHandlerContext 事件传播方法处理的
*
* <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内部实现同时调用了一个Read() 物理层写到外边 |
* 内部的Io线程
* | 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.
* 自下向上处理的入栈处理器通常会处理Io线程生成的数据,通过实际的操作
* <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.
* 进入程序的时候入栈处理为1, 2, 3, 4, 5
* 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>
* 3和4没有实现In接口所以出栈顺序为1,2,5
*也就是 拦截器处理的方式
* <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} {
* //MyInboundHandler 继承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
* 告诉这个管道去运行MyBusinessLogicHandler 的事件处理器
* // 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.
* 这里注意的是,MyBusinessLogicHandler()方法是由group来执行的
* pipeline.addLast(group, "handler", new MyBusinessLogicHandler());
* </pre>
*1 采用addLast()放入一个group 让其MyBusinessLogicHandler 的回调方法在group里面去执行
* 这个线程跟Io线程不是同一个线程,不会阻塞它的方法
* 2 应该在自己处理器里面去创建线程池并且去执行相关方法
* <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.
* 可以插入一个加密的方法在需要的时候同时也可以把他删除掉
*
* 总结: Channel和ChannelPipeline 关系,一个事件从产生到被处理其实是被ChannelPipeline 中一个又一个的完成之后转交给下一个去处理
*/
跟一般拦截器请求处理不同的是,如果出栈的时候不需要经过每一个拦截器,而是看他实现某一个接口,而根据接口类型决定出栈顺序
相关连接
https://www.jianshu.com/p/c551233d5bd8