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(下面解释) 2.ChannelConfig channel的参数,以Map 数据结构来存储 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总是已经被打开了。 此外还有两个事件类型是当父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} { * * private boolean loggedIn; * * {@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); * loggedIn = true; * } else (o instanceof GetDataMessage) { * if ( loggedIn) { * 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( new DataServerHandler()); * } * } 除了这种,每个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); * ctx.setAttachment(true); * } else (o instanceof GetDataMessage) { * if ( Boolean.TRUE.equals(ctx.getAttachment())) { * ch.write(fetchSecret((GetDataMessage) o)); * } else { * fail(); * } * } * } * ... * } * public class DataServerPipelineFactory implements {@link ChannelPipelineFactory} { * * private static final DataServerHandler SHARED = new DataServerHandler(); * * public {@link ChannelPipeline} getPipeline() { * return {@link Channels}.pipeline( SHARED); * } * } 这两种做法还是有区别的,上面的变量做法,每个new的handler 对象,变量是不共享的,而下面的ChannelHandlerContext是共享的 如果需要不同的handler之间共享数据,那怎么办,那就用ChannelLocal 例子: public final class DataServerState { * * public static final {@link ChannelLocal}<Boolean> loggedIn = new {@link ChannelLocal}<Boolean>() { * protected Boolean initialValue(Channel channel) { * return false; * } * } * ... * } * * {@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); * DataServerState.loggedIn.set(ch, true); * } else (o instanceof GetDataMessage) { * if ( DataServerState.loggedIn.get(ch)) { * 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 ( DataServerState.loggedIn.get(ch)) { * System.out.println(ch.getRemoteAddress()); * } * } * 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 而不是自己去构建ChannelPipeline 通常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添加删除channelHandler 需要注意的是,下面的代码写法不能达到预期的效果 * 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。 6.ChannelFactory channel的工厂类,也就是用来生成channel的类,ChannelFactory根据指定的通信和网络来生成相应的channel,比如 NioServerSocketChannelFactory生成的channel是基于NIO server socket的。 当一个channel创建后,ChannelPipeline将作为参数附属给该channel。 对于channelFactory的关闭,需要做两步操作 第一,关闭所有该factory产生的channel包括子channel。通常调用ChannelGroup#close()。 第二,释放channelFactory的资源,调用releaseExternalResources() 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状态常量
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值