netty学习之三 channel和channelHandler

netty中负责传输的核心是channel接口,它用于全部出站的操做。Channel接口的类层次结构以下 [输入图片说明git

  • 每一个Channel都会分配一个ChannelPipeline和ChannelConfig。ChannelConfig负责设置并存储配置,并容许在运行期间更新它们。传输通常有特定的配置设置,只做用于传输,没有其余的实现。ChannelPipeline容纳了使用的ChannelHandler实例,这些ChannelHandler将处理通道传递的“入站”和“出站”数据。
    ChannelHandler的实现容许你改变数据状态和传输数据,channelHandler到底能作哪些事情呢?
  1. • 传输数据时,将数据从一种格式转换到另外一种格式
  2. • 异常通知
  3. • Channel变为有效或无效时得到通知
  4. • Channel被注册或从EventLoop中注销时得到通知
  5. • 通知用户特定事件
  • 这些ChannelHandler实例添加到ChannelPipeline中,在ChannelPipeline中按顺序逐个执行。它相似于一个链条,有使用过Servlet的读者可能会更容易理解。
      ChannelPipeline实现了拦截过滤器模式,这意味着咱们链接不一样的ChannelHandler来拦截并处理通过ChannelPipeline的数据或事件。能够把ChannelPipeline想象成UNIX管道,它容许不一样的命令链(ChannelHandler至关于命令)。你还能够在运行时根据须要添加ChannelHandler实例到ChannelPipeline或从ChannelPipeline中删除,这能帮助咱们构建高度灵活的Netty程序。此外,访问指定的ChannelPipeline和ChannelConfig,你能在Channel自身上进行操做。Channel提供了不少方法,以下列表:
  1. • eventLoop(),返回分配给Channel的EventLoop
  2. • pipeline(),返回分配给Channel的ChannelPipeline
  3. • isActive(),返回Channel是否激活,已激活说明与远程链接对等
  4. • localAddress(),返回已绑定的本地SocketAddress
  5. • remoteAddress(),返回已绑定的远程SocketAddress
  6. • write(),写数据到远程客户端,数据经过ChannelPipeline传输过去
  • 写数据到远程已链接客户端能够调用Channel.write()方法,以下代码:
Channel channel = ...  
ByteBuf buf = Unpooled.copiedBuffer("your data", CharsetUtil.UTF_8);  
ChannelFuture cf = channel.write(buf);  
cf.addListener(new ChannelFutureListener() {  
     @Override  
     public void operationComplete(ChannelFuture future) {  
	        //Write operation completes without error  
	        if (future.isSuccess()) {  
	            System.out.println(.Write successful.);  
	        } else {  
	            //Write operation completed but because of error  
	            System.err.println(.Write error.);  
	            future.cause().printStacktrace();  
	        }  
	    }  
});
  • Channel是线程安全(thread-safe)的,它能够被多个不一样的线程安全的操做,在多线程环境下,全部的方法都是安全的。
  • 下面看下channelHandler和数据如何处理,Handlers自身依赖于ChannelPipeline来决定它们执行的顺序,所以不可能经过ChannelPipeline定义处理程序的某些方面,反过来不可能定义也不可能经过ChannelHandler定义ChannelPipeline的某些方面,Netty的ChannelHandler是你的应用程序中处理最多的。即便你没有意思到这一点,若果你使用Netty应用将至少有一个ChannelHandler参与,换句话说,ChannelHandler对不少事情是关键的。那么ChannelHandler到底是什么?给ChannelHandler一个定义不容易,咱们能够理解为ChannelHandler是一段执行业务逻辑处理数据的代码,它们来来每每的经过ChannelPipeline。实际上,ChannelHandler是定义一个handler的父接口,ChannelInboundHandler和ChannelOutboundHandler都实现ChannelHandler接口,以下图:

输入图片说明

Netty中有两个方向的数据流,上图显示的入站(ChannelInboundHandler)和出站(ChannelOutboundHandler)之间有一个明显的区别:若数据是从用户应用程序到远程主机则是“出站(outbound)”,相反若数据时从远程主机到用户应用程序则是“入站(inbound)”。 为了使数据从一端到达另外一端,一个或多个ChannelHandler将以某种方式操做数据。这些ChannelHandler会在程序的“引导”阶段被添加ChannelPipeline中,而且被添加的顺序将决定处理数据的顺序。ChannelPipeline的做用咱们能够理解为用来管理ChannelHandler的一个容器,每一个ChannelHandler处理各自的数据(例如入站数据只能由ChannelInboundHandler处理),处理完成后将转换的数据放到ChannelPipeline中交给下一个ChannelHandler继续处理,直到最后一个ChannelHandler处理完成。 下图显示了ChannelPipeline的处理过程:github

输入图片说明

  • 上图显示ChannelInboundHandler和ChannelOutboundHandler都要通过相同的ChannelPipeline。
  • 在ChannelPipeline中,若是消息被读取或有任何其余的入站事件,消息将从ChannelPipeline的头部开始传递给第一个ChannelInboundHandler,这个ChannelInboundHandler能够处理该消息或将消息传递到下一个ChannelInboundHandler中,一旦在ChannelPipeline中没有剩余的ChannelInboundHandler后,ChannelPipeline就知道消息已被全部的饿Handler处理完成了。
  • 反过来也是如此,任何出站事件或写入将从ChannelPipeline的尾部开始,并传递到最后一个ChannelOutboundHandler。ChannelOutboundHandler的做用和ChannelInboundHandler相同,它能够传递事件消息到下一个Handler或者本身处理消息。不一样的是ChannelOutboundHandler是从ChannelPipeline的尾部开始,而ChannelInboundHandler是从ChannelPipeline的头部开始,当处理完第一个ChannelOutboundHandler处理完成后会出发一些操做,好比一个写操做。
  • 一个事件能传递到下一个ChannelInboundHandler或上一个ChannelOutboundHandler,在ChannelPipeline中经过使用ChannelHandlerContext调用每个方法。Netty提供了抽象的事件基类称为ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter。每一个都提供了在ChannelPipeline中经过调用相应的方法将事件传递给下一个Handler的方法的实现。咱们能覆盖的方法就是咱们须要作的处理。

** Netty中发送消息有两种方法:直接写入通道或写入ChannelHandlerContext对象。这两种方法的主要区别以下:**安全

  • • 直接写入通道致使处理消息从ChannelPipeline的尾部开始
  • • 写入ChannelHandlerContext对象致使处理消息从ChannelPipeline的下一个handler开始

完整代码连接:https://github.com/winstonelei/Smt多线程

相关文章
相关标签/搜索