`
airu
  • 浏览: 270858 次
  • 性别: Icon_minigender_1
  • 来自: 云南
社区版块
存档分类
最新评论

请您先登录,才能继续操作

netty4.0 关于Handler

 
阅读更多
ChannelHandler是netty中核心, 因为看起来是这样。
我们看看4.0的ChannelHandler,就会发现其实不太一样。
public interface ChannelHandler {

    /**
     * Gets called before the {@link ChannelHandler} is added to the actual context.
     */
    void beforeAdd(ChannelHandlerContext ctx) throws Exception;

    /**
     * Gets called after the {@link ChannelHandler} was added to the actual context.
     */
    void afterAdd(ChannelHandlerContext ctx) throws Exception;

    /**
     * Gets called before the {@link ChannelHandler} is removed from the actual context.
     */
    void beforeRemove(ChannelHandlerContext ctx) throws Exception;

    /**
     * Gets called after the {@link ChannelHandler} was removed from the actual context.
     */
    void afterRemove(ChannelHandlerContext ctx) throws Exception;

    /**
     * Gets called if a {@link Throwable} was thrown.
     */
    void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;

    /**
     * Gets called if an user event was triggered.
     */
    void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception;
}

这里略去一个注解的声明--Sharable
同时我没有列出对这个接口的注释。其实这个注释是3.5的还没更新。因为3.5到4.0还是有很大不同,我们来看看。
一个handler的接口,应该是定义我们应该处理一些什么情况见函数:
  /**
     * Gets called if an user event was triggered.
  */
 void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception;

ChannelHandler 定义了事件接口。在仔细看这些事件接口,我们可以发现,都有一个ChannelHanderContext,注释中也说明,handler是注册到了ChannelHanderContext上的。所以,我们就看看ChannelHanderContext类吧。
public interface ChannelHandlerContext
         extends AttributeMap, ChannelPropertyAccess,
                 ChannelInboundInvoker, ChannelOutboundInvoker {
...
}


这里的ChannelInboundInvoker接口基本上就是拥有通知Channel上的各种事件的能力,二ChannelOutboundInvoker则是具备了向管道外写数据,连接等功能。注意返回值都是ChannelFuture这就说明这些操作都是异步的。
总之ChannelOutboundInvoker是Channel,ChannelhandlerContext, ChannelPipeline的父接口。
好了,不要跑题了。对于ChannelHandlerContext来说,基本上就是对传输过程中的各个方面的管理器。包括ChannelHandler的注册销毁等等。

而对于ChannelHandler来说,有很多很多子接口,实现类。具体来说可通过ChannelHandlerType可以分为2类,4个type
public enum ChannelHandlerType {
    STATE(0),
    INBOUND(0),
    OPERATION(1),
    OUTBOUND(1);

    final int direction; // 0 - up (inbound), 1 - down (outbound)

    ChannelHandlerType(int direction) {
        if (direction != 0 && direction != 1) {
            throw new IllegalArgumentException("direction must be either 0 or 1");
        }
        this.direction = direction;
    }
}


从这里可以看到,每个ChannelHander都是有方向性的。这里的方向性,也就是管道中inbound和outbound的意思。所以ChannelHander的两个子接口 ChannelOperationHandler 也就是outbound 和ChannelStateHandler 也就是inbound。围绕着in与out,又催生出子接口 ChannelOutboundHandler 和 ChannelInboundHandler。再下来,就是各种处理,基本不外乎 byte和message之间的转换。

这里有很多两个常用的Adapter,
  • ChannelInboundMessageHandlerAdapter<T>
  • ChannelInboundByteHandlerAdapter


对于ChannelInboundMessageHandlerAdapter<T>最主要的就是当消息到来时的处理,函数:
public void messageReceived(ChannelHandlerContext ctx, I msg) throws Exception;
将由用户去实现。

而对于ChannelInboundByteHandlerAdapter来说,函数和ChannelStateHandler的接口类似,被封装成:
/**
     * Callback which will get notifed once the given {@link ByteBuf} received more data to read. What will be done
     * with the data at this point is up to the implementation.
     * Implementations may choose to read it or just let it in the buffer to read it later.
     */
    public abstract void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) throws Exception;


那么,handler是如何在事件发生时被调用的呢?
其实这应该是ChannelHandlerContext 告诉handler的,我们看下DefaultChannelHandlerContext就知道了。ChannelHandlerContext接口不具备了事件通知功能,也具备了管道的能力。

从DefaultChannelHandlerContext构造函数看
  DefaultChannelHandlerContext(
            DefaultChannelPipeline pipeline, EventExecutorGroup group,
            DefaultChannelHandlerContext prev, DefaultChannelHandlerContext next,
            String name, ChannelHandler handler)
最主要的几个成员变量就是这几个参数。从prev和next我们可以初步判断出这个ChannelHandlerContext 并不是单一出现的,而是linked的。

在来看pipeline,也有一个实现类DefaultChannelPipeline,构造函数为:
  public DefaultChannelPipeline(Channel channel)
这也看得出这是对一个Channel的封装。再看成员变量,有
 final DefaultChannelHandlerContext head;
    private volatile DefaultChannelHandlerContext tail;
    private final Map<String, DefaultChannelHandlerContext> name2ctx =
        new HashMap<String, DefaultChannelHandlerContext>(4);

于是猜到最终的ChannelHandlerContext是在这里生成的,而且是链式的。
来看看我们最常用的函数 addFirst
    @Override
    public ChannelPipeline addFirst(String name, ChannelHandler handler) {
        return addFirst(null, name, handler);
    }

    @Override
    public ChannelPipeline addFirst(EventExecutorGroup group, final String name, ChannelHandler handler) {
        final DefaultChannelHandlerContext nextCtx;
        final DefaultChannelHandlerContext newCtx;

        synchronized (this) {
            checkDuplicateName(name);
            nextCtx = head.next;
            newCtx = new DefaultChannelHandlerContext(this, group, head, nextCtx, name, handler);

            if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) {
                addFirst0(name, nextCtx, newCtx);
                return this;
            }
        }

        // Run the following 'waiting' code outside of the above synchronized block
        // in order to avoid deadlock

        newCtx.executeOnEventLoop(new Runnable() {
                @Override
                public void run() {
                    synchronized (DefaultChannelPipeline.this) {
                        checkDuplicateName(name);
                        addFirst0(name, nextCtx, newCtx);
                    }
                }
            });

        return this;
    }

    private void addFirst0(
            final String name, DefaultChannelHandlerContext nextCtx, DefaultChannelHandlerContext newCtx) {
        callBeforeAdd(newCtx);

        if (nextCtx != null) {
            nextCtx.prev = newCtx;
        }
        head.next = newCtx;
        if (tail == head) {
            tail = newCtx;
        }

        name2ctx.put(name, newCtx);

        callAfterAdd(newCtx);
    }

这里基本就是对链表的处理了。DefaultChannelHandlerContext中还定义了一些事件任务。这些任务都是在EventLoop中提交的。使用EventExecutor。这些事件是用来通知链上的下一个ChannelHandlerContext,具体是什么需要看handler的方向了。

至此,ChannelHandler就差不多了,接下来该看看EventLoop是如何工作的了。
0
1
分享到:
评论

相关推荐

    Netty4.0学习笔记系列之四:混合使用coder和handler

    在本篇Netty4.0学习笔记中,我们将聚焦于如何在实际应用中混合使用`coder`和`handler`,这是Netty框架中非常关键的一部分,对于构建高性能、低延迟的网络应用程序至关重要。Netty是一个用Java编写的异步事件驱动的...

    Netty4.0学习笔记系列之二:Handler的执行顺序

    在本篇“Netty4.0学习笔记系列之二:Handler的执行顺序”中,我们将深入探讨Netty中的Handler处理链以及它们的执行流程。 首先,Netty 中的 ChannelHandler 是处理 I/O 事件或拦截 I/O 操作的核心组件。每个 ...

    netty4.0文件分片上传+断点续传+权限校验

    在本文中,我们将深入探讨如何利用Netty 4.0实现文件分片上传、断点续传以及权限校验的功能。 **文件分片上传** 文件分片上传是为了处理大文件传输时,避免一次性加载整个文件到内存中,从而减少内存消耗和提高...

    netty4.0 demo

    这个"Netty4.0 demo"压缩包包含了一些Netty 4.0版本的应用示例代码,可以帮助我们更好地理解和学习Netty的工作原理以及如何在实际项目中运用它。 1. **Netty简介** Netty 是由JBOSS组织开发的一个开源项目,最初...

    netty4.0源码,netty例子,netty api文档

    Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个压缩包包含的是Netty 4.0.0.CR3版本的相关资源,包括源码、示例以及API文档,对于学习和理解Netty的工作...

    Netty4.0学习笔记系列之五:自定义通讯协议

    在本篇“Netty4.0学习笔记系列之五:自定义通讯协议”中,我们将深入探讨如何在Netty框架下构建和实现自己的通信协议。Netty是一个高性能、异步事件驱动的网络应用框架,广泛应用于Java领域的服务器开发,如网络游戏...

    Netty4.0学习笔记系列之一:Server与Client的通讯

    在本文中,我们将深入探讨Netty 4.0的学习笔记,特别是关于Server与Client之间的通信机制。 首先,我们要理解Netty的核心概念——NIO(非阻塞I/O)。Netty基于Java NIO库构建,它提供了更高级别的API,简化了多路...

    netty-4.0.41-2016-9-29官网下载

    这个“netty-4.0.41-2016-9-29官网下载”指的是2016年9月29日从Netty官方获取的4.0.41版本的Netty框架。"netty-all-in-one"可能表示这个压缩包包含了Netty框架的所有组件和依赖,方便开发者一次性获取并进行开发。 ...

    Netty开发资源.rar

    Netty的API中文开发文档对于中国开发者来说尤其宝贵,它详细解释了Netty的各种组件和接口,包括Channel、EventLoop、ByteBuf、Handler等关键概念。通过这些文档,开发者可以了解如何创建自定义的协议解码器和编解码...

    netty.chm nettyapi

    5. **Pipeline**:Netty的处理链模式,每个Channel都有一个ChannelPipeline,其中包含了多个ChannelHandler,数据在Pipeline中从头到尾传递,每个Handler可以对数据进行处理或转发。 6. **Handlers**:...

    netty-all-4.0.0.Final-source

    2. **高度可定制化**:Netty提供了一套灵活的“管道”(Pipeline)和“处理程序”(Handler)机制,允许开发者自定义数据处理流程。每个连接都有一个与之关联的管道,处理程序链可以按照需求添加或移除。 3. **丰富...

    netty4 Android客户端和服务器端

    在本文中,我们将深入探讨如何使用 Netty 4.0.31.Final 版本构建 Android 客户端和服务器端应用程序。 首先,Netty 提供了一种简化网络编程的方式,它通过非阻塞 I/O 和 Channel 抽象来处理并发连接。在 Android 上...

    使用netty自定义rpc通信框架

    本项目是基于Netty 4.0实现的自定义RPC通信框架,旨在为Java开发者提供一种高效、灵活的远程服务调用解决方案。 首先,我们来深入理解Netty的基本概念。Netty的核心是其NIO(非阻塞I/O)模型,它使用了Reactor模式...

    微信jssdk1.4.0

    描述中提到的“netty4.0服务端程序”是指基于Netty框架构建的服务器端应用。Netty是一个高性能、异步事件驱动的网络应用框架,用于快速开发可维护的高性能协议服务器和客户端。Netty4.0是其一个重要的版本,带来了...

Global site tag (gtag.js) - Google Analytics