Netty Channel 接口名词理解

 

1.Channel
channel 是负责数据读,写的对象,有点相似于老的io里面的stream,他和stream的区别,channel是双向的
既能够write 也能够read,而stream要分outstream和inputstream。并且在NIO中用户不该该直接从channel中读写数据,
而是应该经过buffer,经过buffer再将数据读写到channel中。
一个channel 能够提供给用户下面几个信息
(1)channel的当前状态,好比open 仍是closed
(2)ChannelConfig对象,表示channel的一些参数,好比bufferSize
(3)channel支持的全部i/o操做(好比read,write,connect.bind)以及ChannelPipeLine(下面解释)html

2.ChannelConfig
channel的参数,以Map 数据结构来存储java

3.ChannelEvent
ChannelEvent广义的认为Channel相关的事件,他是否分Upstream events和downstream events两大块,这里须要注意的,让是server为
主体的话,从client的数据到server的过程是Upstream;而server到client的数据传输过程叫downstream;而若是以client为主体
的话,从server到client的过程对client来讲是Upstream,而client到server的过程对client来讲就是downstream。
Upstream events包括:
messageReceived:信息被接受时 ---MessageEvent
exceptionCaught:产生异常时 ---ExceptionEvent
channelOpen:channel被开启时 ---ChannelStateEvent
channelClosed:channel被关闭时 ---ChannelStateEvent
channelBound:channel被开启并准备去链接但还未链接上的时候 ---ChannelStateEvent
channelUnbound:channel被开启不许备去链接时候 ---ChannelStateEvent
channelConnected:channel被链接上的时候 ---ChannelStateEvent
channelDisconnected:channel链接断开的时候 ---ChannelStateEvent
channelInterestChanged:Channel的interestOps被改变的时候 ------ChannelStateEvent
writeComplete:写到远程端完成的时候 --WriteCompletionEvent网络

Downstream events包括:
write:发送信息给channel的时候 --MessageEvent
bind:绑定一个channel到指定的本地地址 --ChannelStateEvent
unbind:解除当前本地端口的绑定--ChannelStateEvent
connect:将channel链接到远程的机 --ChannelStateEvent
disconnect:将channel与远程的机链接断开 --ChannelStateEvent
close:关闭channel --ChannelStateEvent数据结构

须要注意的是,这里没有open event,这是由于当一个channel被channelFactory建立的话,channel老是已经被打开了。app

此外还有两个事件类型是当父channel存在子channel的状况
childChannelOpen:子channel被打开 ---ChannelStateEvent
childChannelClosed:子channel被关闭 ---ChannelStateEvent异步

4.ChannelHandler
channel是负责传送数据的载体,那么数据确定须要根据要求进行加工处理,那么这个时候就用到ChannelHandler
不一样的加工能够构建不一样的ChannelHandler,而后放入ChannelPipeline中
此外须要有ChannelEvent触发后才能到达ChannelHandler,所以根据event不一样有下面两种的sub接口ChannelUpstreamHandler
和ChannelDownstreamHandler。
一个ChannelHandler一般须要存储一些状态信息做为判断信息,经常使用作法定义一个变量
好比
public class DataServerHandler extends {@link SimpleChannelHandler} {
 *
 *     <b>private boolean loggedIn;</b>
 *
 *     {@code @Override}
 *     public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
 *         {@link Channel} ch = e.getChannel();
 *         Object o = e.getMessage();
 *         if (o instanceof LoginMessage) {
 *             authenticate((LoginMessage) o);
 *             <b>loggedIn = true;</b>
 *         } else (o instanceof GetDataMessage) {
 *             if (<b>loggedIn</b>) {
 *                 ch.write(fetchSecret((GetDataMessage) o));
 *             } else {
 *                 fail();
 *             }
 *         }
 *     }
 *     ...
 * }
 
 // Create a new handler instance per channel.
 * // See {@link Bootstrap#setPipelineFactory(ChannelPipelineFactory)}.
 * public class DataServerPipelineFactory implements {@link ChannelPipelineFactory} {
 *     public {@link ChannelPipeline} getPipeline() {
 *         return {@link Channels}.pipeline(<b>new DataServerHandler()</b>);
 *     }
 * }
 
除了这种,每一个ChannelHandler均可以从ChannelHandlerContext中获取或设置数据,那么下面的作法就是利用ChannelHandlerContext
设置变量
* {@code @Sharable}
 * public class DataServerHandler extends {@link SimpleChannelHandler} {
 *
 *     {@code @Override}
 *     public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
 *         {@link Channel} ch = e.getChannel();
 *         Object o = e.getMessage();
 *         if (o instanceof LoginMessage) {
 *             authenticate((LoginMessage) o);
 *             <b>ctx.setAttachment(true)</b>;
 *         } else (o instanceof GetDataMessage) {
 *             if (<b>Boolean.TRUE.equals(ctx.getAttachment())</b>) {
 *                 ch.write(fetchSecret((GetDataMessage) o));
 *             } else {
 *                 fail();
 *             }
 *         }
 *     }
 *     ...
 * }
 
 * public class DataServerPipelineFactory implements {@link ChannelPipelineFactory} {
 *
 *     private static final DataServerHandler <b>SHARED</b> = new DataServerHandler();
 *
 *     public {@link ChannelPipeline} getPipeline() {
 *         return {@link Channels}.pipeline(<b>SHARED</b>);
 *     }
 * }
 这两种作法仍是有区别的,上面的变量作法,每一个new的handler 对象,变量是不共享的,而下面的ChannelHandlerContext是共享的
 
 若是须要不一样的handler之间共享数据,那怎么办,那就用ChannelLocal
 例子:
  public final class DataServerState {
 *
 *     <b>public static final {@link ChannelLocal}&lt;Boolean&gt; loggedIn = new {@link ChannelLocal}&lt;Boolean&gt;() {
 *         protected Boolean initialValue(Channel channel) {
 *             return false;
 *         }
 *     }</b>
 *     ...
 * }
 *
 * {@code @Sharable}
 * public class DataServerHandler extends {@link SimpleChannelHandler} {
 *
 *     {@code @Override}
 *     public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
 *         Channel ch = e.getChannel();
 *         Object o = e.getMessage();
 *         if (o instanceof LoginMessage) {
 *             authenticate((LoginMessage) o);
 *             <b>DataServerState.loggedIn.set(ch, true);</b>
 *         } else (o instanceof GetDataMessage) {
 *             if (<b>DataServerState.loggedIn.get(ch)</b>) {
 *                 ctx.getChannel().write(fetchSecret((GetDataMessage) o));
 *             } else {
 *                 fail();
 *             }
 *         }
 *     }
 *     ...
 * }
 *
 * // Print the remote addresses of the authenticated clients:
 * {@link ChannelGroup} allClientChannels = ...;
 * for ({@link Channel} ch: allClientChannels) {
 *     if (<b>DataServerState.loggedIn.get(ch)</b>) {
 *         System.out.println(ch.getRemoteAddress());
 *     }
 * }
 * </pre>
 
5.ChannelPipeline
channelPipeline是一系列channelHandler的集合,他参照J2ee中的Intercepting Filter模式来实现的,
让用户彻底掌握若是在一个handler中处理事件,同时让pipeline里面的多个handler能够相互交互。
Intercepting Filter:http://java.sun.com/blueprints/corej2eepatterns/Patterns/InterceptingFilter.html
对于每个channel都须要有相应的channelPipeline,当为channel设置了channelPipeline后就不能再为channel从新设置
channelPipeline。此外建议的作法的经过Channels 这个帮助类来生成ChannelPipeline 而不是本身去构建ChannelPipelinesocket

一般pipeLine 添加多个handler,是基于业务逻辑的
好比下面
{@link ChannelPipeline} p = {@link Channels}.pipeline();
 * p.addLast("1", new UpstreamHandlerA());
 * p.addLast("2", new UpstreamHandlerB());
 * p.addLast("3", new DownstreamHandlerA());
 * p.addLast("4", new DownstreamHandlerB());
 * p.addLast("5", new SimpleChannelHandler());
 upstream event 执行的handler按顺序应该是 125
 downstream event 执行的handler按顺序应该是 543
 SimpleChannelHandler 是同时实现了 ChannelUpstreamHandler和ChannelDownstreamHandler的类
上面只是具备逻辑,若是数据须要经过格式来进行编码的话,那须要这些写
 * {@link ChannelPipeline} pipeline = {@link Channels#pipeline() Channels.pipeline()};
 * pipeline.addLast("decoder", new MyProtocolDecoder());
 * pipeline.addLast("encoder", new MyProtocolEncoder());
 * pipeline.addLast("executor", new {@link ExecutionHandler}(new {@link OrderedMemoryAwareThreadPoolExecutor}(16, 1048576, 1048576)));
 * pipeline.addLast("handler", new MyBusinessLogicHandler());
 其中:
Protocol Decoder - 将binary转换为java对象
Protocol Encoder - 将java对象转换为binary
ExecutionHandler - applies a thread model.
Business Logic Handler - performs the actual business logic(e.g. database access)
虽然不能为channel从新设置channelPipeline,可是channelPipeline自己是thread-safe,所以你能够在任什么时候候为channelPipeline添加删除channelHandleride

须要注意的是,下面的代码写法不能达到预期的效果
 * public class FirstHandler extends {@link SimpleChannelUpstreamHandler} {
 *
 *     {@code @Override}
 *     public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
 *         // Remove this handler from the pipeline,
 *         ctx.getPipeline().remove(this);
 *         // And let SecondHandler handle the current event.
 *         ctx.getPipeline().addLast("2nd", new SecondHandler());
 *         ctx.sendUpstream(e);
 *     }
 * }
 前提如今Pipeline只有最后一个FirstHandler,
 上面明显是想把FirstHandler从Pipeline中移除,而后添加SecondHandler。而pipeline须要只要有一个Handler,所以若是想到到达这个效果,那么能够
 先添加SecondHandler,而后在移除FirstHandler。fetch

6.ChannelFactory
channel的工厂类,也就是用来生成channel的类,ChannelFactory根据指定的通讯和网络来生成相应的channel,好比
NioServerSocketChannelFactory生成的channel是基于NIO server socket的。
当一个channel建立后,ChannelPipeline将做为参数附属给该channel。
对于channelFactory的关闭,须要作两步操做
第一,关闭全部该factory产生的channel包括子channel。一般调用ChannelGroup#close()。
第二,释放channelFactory的资源,调用releaseExternalResources()this

7.ChannelGroup
 channel的组集合,他包含一个或多个open的channel,closed channel会自动从group中移除,一个channel能够在一个或者多个channelGroup
 若是想将一个消息广播给多个channel,能够利用group来实现
 好比:
{@link ChannelGroup} recipients = new {@link DefaultChannelGroup}()
recipients.add(channelA);
recipients.add(channelB);
recipients.write(ChannelBuffers.copiedBuffer("Service will shut down for maintenance in 5 minutes.",CharsetUtil.UTF_8));

当ServerChannel和非ServerChannel同时都在channelGroup中的时候,任何io请求的操做都是先在ServerChannel中执行再在其余Channel中执行。
这个规则对关闭一个server很是适用。
 
8.ChannelFuture
在netty中,全部的io传输都是异步,全部那么在传送的时候须要数据+状态来肯定是否所有传送成功,而这个载体就是ChannelFuture。

9.ChannelGroupFuture
针对一次ChannelGroup异步操做的结果,他和ChannelFuture同样,包括数据和状态。不一样的是他由channelGroup里面channel的全部channelFuture
组成。

10.ChannelGroupFutureListener
针对ChannelGroupFuture的监听器,一样建议使用ChannelGroupFutureListener而不是await();

11.ChannelFutureListener
ChannelFuture监听器,监听channelFuture的结果。

12.ChannelFutureProgressListener
监听ChannelFuture处理过程,好比一个大文件的传送。而ChannelFutureListener只监听ChannelFuture完成未完成

13.ChannelHandlerContext
如何让handler和他的pipeLine以及pipeLine中的其余handler交换,那么就要用到ChannelHandlerContext,
ChannelHandler能够经过ChannelHandlerContext的sendXXXstream(ChannelEvent)将event传给最近的handler
能够经过ChannelHandlerContext的getPipeline来获得Pipeline,并修改他,ChannelHandlerContext还能够存放一下状态信息attments。
一个ChannelHandler实例能够有一个或者多个ChannelHandlerContext

14.ChannelPipelineFactory
产生ChannelPipe的工厂类

15.ChannelState 记载channel状态常量

相关文章
相关标签/搜索