【转】http://blog.csdn.net/zxhoo/article/details/17264263
Netty4
Netty是一个和MINA类似的Java NIO框架,目前的最新版本是4.0.13,这两个框架的主要作者好像都是同一个韩国人。
Channel
Channel是Netty最核心的接口,一个Channel就是一个联络Socket的通道,通过Channel,你可以对Socket进行各种操作。
ChannelHandler
用Netty编写网络程序的时候,你很少直接操纵Channel,而是通过ChannelHandler来间接操纵Channel。
ChannelPipeline
ChannelPipeline实际上应该叫做ChannelHandlerPipeline,可以把ChannelPipeline看成是一个ChandlerHandler的链表,当需要对Channel进行某种处理的时候,Pipeline负责依次调用每一个Handler进行处理。每个Channel都有一个属于自己的Pipeline,调用Channel#pipeline()方法可以获得Channel的Pipeline,调用Pipeline#channel()方法可以获得Pipeline的Channel。
ChannelPipeline的方法有很多,其中一部分是用来管理ChannelHandler的,如下面这些:
- ChannelPipeline addFirst(String name, ChannelHandler handler);
- ChannelPipeline addLast(String name, ChannelHandler handler);
- ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler);
- ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler);
- ChannelPipeline remove(ChannelHandler handler);
- ChannelHandler remove(String name);
- ChannelHandler removeFirst();
- ChannelHandler removeLast();
- ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);
- ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler);
- ChannelHandler first();
- ChannelHandler last();
- ChannelHandler get(String name);
根据上面的方法,能够大概想象的到Pipeline按照什么样的方式组织Handler。
ChannelHandlerContext
ChannelPipeline并不是直接管理ChannelHandler,而是通过ChannelHandlerContext来间接管理,这一点通过ChannelPipeline的默认实现DefaultChannelPipeline可以看出来。
调用ChannelHandlerContext#channel()方法可以得到和Context绑定的Channel,调用ChannelHandlerContext#handler()方法可以得到和Context绑定的Handler。
ChannelPipeline和ChannelHandlerContext默认实现
DefaultChannelHandlerContext和DefaultChannelPipeline是ChannelHandlerContext和ChannelPipeline的默认实现,下面是它们的部分代码:
- final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {
- volatile DefaultChannelHandlerContext next;
- volatile DefaultChannelHandlerContext prev;
- private final boolean inbound;
- private final boolean outbound;
- private final AbstractChannel channel;
- private final DefaultChannelPipeline pipeline;
- private final String name;
- private final ChannelHandler handler;
- private boolean removed;
- // ...
- }
- final class DefaultChannelPipeline implements ChannelPipeline {
- // ...
- final DefaultChannelHandlerContext head;
- final DefaultChannelHandlerContext tail;
- // ...
- }
从上面的代码可以看出,在DefaultPipeline内部,DefaultChannelHandlerContext组成了一个双向链表:
再来看看DefaultChannelPipeline的构造函数:
- public DefaultChannelPipeline(AbstractChannel channel) {
- if (channel == null) {
- throw new NullPointerException("channel");
- }
- this.channel = channel;
- TailHandler tailHandler = new TailHandler();
- tail = new DefaultChannelHandlerContext(this, null, generateName(tailHandler), tailHandler);
- HeadHandler headHandler = new HeadHandler(channel.unsafe());
- head = new DefaultChannelHandlerContext(this, null, generateName(headHandler), headHandler);
- head.next = tail;
- tail.prev = head;
- }
可以看到,DefaultChinnelPipeline内部使用了两个特殊的Handler来表示Handler链的头和尾:
ChannelHandler的种类
从上面DefaultChannelHandlerContext代码可以知道,Handler实际上分为两种,Inbound和Outbound,这一点也可以从ChannelHandler接口的子接口得到证明:
- public interface ChannelInboundHandler extends ChannelHandler {
- // ...
- }
- public interface ChannelOutboundHandler extends ChannelHandler {
- // ...
- }
事件的传播
为了搞清楚事件如何在Pipeline里传播,让我们从Channel的抽象子类AbstractChannel开始,下面是AbstractChannel#write()方法的实现:
- public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
- // ...
- @Override
- public Channel write(Object msg) {
- return pipeline.write(msg);
- }
- // ...
- }
AbstractChannel直接调用了Pipeline的write()方法:
再看DefaultChannelPipeline的write()方法实现:
- final class DefaultChannelPipeline implements ChannelPipeline {
- // ...
- @Override
- public ChannelFuture write(Object msg) {
- return tail.write(msg);
- }
- // ...
- }
因为write是个outbound事件,所以DefaultChannelPipeline直接找到tail部分的context,调用其write()方法:
接着看DefaultChannelHandlerContext的write()方法:
- final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {
- // ...
- @Override
- public ChannelFuture write(Object msg) {
- return write(msg, newPromise());
- }
- @Override
- public ChannelFuture write(final Object msg, final ChannelPromise promise) {
- if (msg == null) {
- throw new NullPointerException("msg");
- }
- validatePromise(promise, true);
- write(msg, false, promise);
- return promise;
- }
- private void write(Object msg, boolean flush, ChannelPromise promise) {
- DefaultChannelHandlerContext next = findContextOutbound();
- next.invokeWrite(msg, promise);
- if (flush) {
- next.invokeFlush();
- }
- }
- private DefaultChannelHandlerContext findContextOutbound() {
- DefaultChannelHandlerContext ctx = this;
- do {
- ctx = ctx.prev;
- } while (!ctx.outbound);
- return ctx;
- }
- private void invokeWrite(Object msg, ChannelPromise promise) {
- try {
- ((ChannelOutboundHandler) handler).write(this, msg, promise);
- } catch (Throwable t) {
- notifyOutboundHandlerException(t, promise);
- }
- }
- // ...
- }
context的write()方法沿着context链往前找,直至找到一个outbound类型的context为止,然后调用其invokeWrite()方法:
invokeWrite()接着调用handler的write()方法:
最后看看ChannelOutboundHandlerAdapter的write()方法实现:
- public class ChannelOutboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelOutboundHandler {
- // ...
- @Override
- public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
- ctx.write(msg, promise);
- }
- // ...
- }
默认的实现调用了context的write()方法而不做任何处理,这样write事件就沿着outbound链继续传播:
可见,Pipeline的事件传播,是靠Pipeline,Context和Handler共同协作完成的。
相关推荐
管道(ChannelPipeline)是DotNetty的核心组件,它负责处理进来的网络事件,并按照预设的顺序传递给各个处理器(ChannelHandler)。 接下来,我们关注如何定义自定义协议。这通常涉及到解析和构建消息的逻辑。在...
这些处理器可以被添加到Netty的管道(`ChannelPipeline`)中,以便在数据传输时自动应用。 6. **LIQUIDSOCKETSERVER 示例** 压缩包中的 "LIQUIDSOCKETSERVER" 文件可能是Netty服务器的源代码示例,它可能展示了...
在Netty服务器端,我们需要定义一个ChannelInitializer,它会在新的连接建立时初始化ChannelPipeline。在这个管道中,我们可以添加各种处理器,如解码器和编码器,来处理进来的和发送出去的数据。对于Marshaling编...
编解码器(Codec)是网络应用程序中非常重要的一部分,它负责将原始字节数据与自定义的消息对象进行互转。在Netty框架中,编解码器由两部分组成:Decoder(解码器)和Encoder(编码器)。解码器负责将消息从字节或...
解码器的使用场景通常是在 `ChannelPipeline` 中,当需要对入站数据进行转换以适应后续处理器(ChannelInboundHandler)时。在 `ChannelPipeline` 中,你可以连接多个解码器以实现复杂的数据转换逻辑。例如,你可能...
通过它,Handler 可以调用 Channel 的方法,或者向 ChannelPipeline 中的下一个 Handler 传递事件。 5. **Bootstrap 和 ServerBootstrap**:Bootstrap 用于创建客户端连接,ServerBootstrap 用于创建服务器。它们都...
在本章《Netty in Action》的中文版中,作者主要介绍了Netty框架中的核心类,包括Bootstrap、ServerBootstrap、EventLoop、EventLoopGroup、ChannelPipeline、ChannelFuture、ChannelInitializer和ChannelHandler等...
为了在Netty管道中使用这些编码器和解码器,我们需要将它们添加到 ChannelPipeline 中。例如: ```java ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("decoder", new CustomMessageDecoder()); ...
4. **ChannelHandler** 和 **ChannelPipeline**:ChannelHandler 处理 Channel 上的事件,ChannelPipeline 是 ChannelHandler 的链式结构,处理入站和出站事件。 5. **ByteBuf**:Netty 的高效字节缓冲区,替代了...
ChannelPipeline 可以理解为一系列 ChannelHandler 的容器,当数据通过 Channel 流动时,会依次经过 ChannelPipeline 中的每个 Handler。Handler 的执行顺序由它们在 Pipeline 中的位置决定,一般遵循“先进先出”...
然后,你可以在你的 ChannelPipeline 中添加这两个自定义编解码器,确保它们的顺序正确(编码器应该在解码器之前): ```java ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new ...
Netty服务器端通常由多个组件构成,包括Bootstrap、ServerBootstrap、ChannelFuture、ChannelHandler和ChannelPipeline等。Bootstrap是服务器端启动器,用来配置服务器的连接参数,如绑定的IP地址和端口。...
`ChannelPipeline`则是一系列`ChannelHandler`的链表,负责在`Channel`上按顺序调用这些处理器,实现了数据的双向传递和事件的处理。 5. **Bootstrap 和 ServerBootstrap**: `Bootstrap`用于创建客户端连接,而`...
4. **ChannelPipeline**:ChannelPipeline是处理I/O事件的链条,它包含了一系列ChannelHandler。当数据从网络流入或流出时,它们会在pipeline中的各个handler之间传递,每个handler可以对其进行处理或转发。 5. **...
最后,我们需要在服务器的 ChannelPipeline 中添加这个自定义的解码器: ```java ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())...
它不仅支持传统的客户端-服务器模型,还能通过ChannelPipeline机制实现各种协议的编解码器,并将各种协议消息转换为统一的消息格式。Netty中的ChannelPipeline相当于一组拦截过滤器,用于在数据流经Channel时,对其...
服务器启动时,会创建一个 `Bootstrap` 实例,绑定一个端口,并添加 `ChannelInitializer`,在这个初始化器中,我们可以设置 `ChannelPipeline`,将我们的 `ChannelHandler` 添加到管道中。当有新的连接建立时,...
3. 通道处理流程:Netty中的数据处理流程是通过ChannelPipeline来完成的,每个Channel都有一个与之关联的ChannelPipeline。当一个消息或特定的I/O事件被触发时,它会沿着ChannelPipeline传播,由ChannelHandler链...
在JavaNettyProj中,服务器端(Server)会通过Bootstrap配置一个ServerBootstrap实例,绑定监听端口,并设置ChannelPipeline,这个管道会包含解码和编码的处理器,例如ByteToMessageDecoder和MessageToByteEncoder,...