Netty源码—5.Pipeline和Handler二

大纲

1.Pipeline和Handler的作用和构成

2.ChannelHandler的分类

3.几个特殊的ChannelHandler

4.ChannelHandler的生命周期

5.ChannelPipeline的事件处理

6.关于ChannelPipeline的问题整理

7.ChannelPipeline主要包括三部分内容

8.ChannelPipeline的初始化

9.ChannelPipeline添加ChannelHandler

10.ChannelPipeline删除ChannelHandler

11.Inbound事件的传播

12.Outbound事件的传播

13.ChannelPipeline中异常的传播

14.ChannelPipeline总结

10.ChannelPipeline删除ChannelHandler

Netty最大的特征之一就是ChannelHandler是可插拔的,可以动态编织ChannelPipeline。比如在客户端首次连接服务端时,需要进行权限认证,认证通过后就可以不用再认证了。下面的AuthHandler便实现了只对第一个传来的数据包进行认证校验。如果通过验证则删除此AuthHandler,这样后续传来的数据包便不会再校验了。

public class AuthHandler extends SimpleChannelInboundHandler<ByteBuf> {
    ...
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf data) throw Exception {
        if (verify(data)) {
            ctx.pipeline().remove(this);     
        } else {
            ctx.close();
        }
    }
}

DefaultChannelPipeline的remove()方法如下:

public class DefaultChannelPipeline implements ChannelPipeline {
    ...
    @Override
    public final ChannelPipeline remove(ChannelHandler handler) {
        remove(getContextOrDie(handler));
        return this;
    }
    
    private AbstractChannelHandlerContext getContextOrDie(ChannelHandler handler) {
        AbstractChannelHandlerContext ctx = (AbstractChannelHandlerContext) context(handler);
        if (ctx == null) {
            throw new NoSuchElementException(handler.getClass().getName());
        } else {
            return ctx;
        }
    }
    
    @Override
    public final ChannelHandlerContext context(ChannelHandler handler) {
        ...
        AbstractChannelHandlerContext ctx = head.next;
        //遍历双向链表
        for (;;) {
            ...
            if (ctx.handler() == handler) return ctx;
            ctx = ctx.next;
        }
    }
    
    private AbstractChannelHandlerContext remove(final AbstractChannelHandlerContext ctx) { 
        //Pipeline中的head和tail结点不能被删除
        assert ctx != head && ctx != tail;
        synchronized (this) {
            //调整链表指针并删除
            remove0(ctx);
            ...
        }
        //回调用户在这个要删除的ChannelHandler实现的handlerRemoved()方法
        callHandlerRemoved0(ctx);
        return ctx;
    }

    private static void remove0(AbstractChannelHandlerContext ctx) {
        AbstractChannelHandlerContext prev = ctx.prev;
        AbstractChannelHandlerContext next = ctx.next;
        prev.next = next;
        next.prev = prev;
    }
    
    private void callHandlerRemoved0(final AbstractChannelHandlerContext ctx) {
        ...
        ctx.handler().handlerRemoved(ctx);
        ...
    }
    ...
}

ChannelPipeline删除ChannelHandler的步骤:

一.遍历双向链表,根据ChannelHandler找到对应的ChannelHandlerContext结点。

二.通过调整ChannelPipeline中双向链表的指针来删除对应的ChannelHandlerContext结点。

三.回调用户在这个要删除的ChannelHandler实现的handlerRemoved()方法,比如进行资源清理。

11.Inbound事件的传播

(1)Unsafe的介绍

(2)Unsafe的继承结构

(3)Unsafe的分类

(4)ChannelPipeline中Inbound事件传播

(5)ChannelPipeline中的头结点和尾结点

(6)Inbound事件的传播总结

(1)Unsafe的介绍

Unsafe和ChannelPipeline密切相关,ChannelPipeline中有关IO的操作最终都会落地到Unsafe的。Unsafe是不安全的意思,即不要在应用程序里直接使用Unsafe及它的衍生类对象。Unsafe是在Channel中定义的,是属于Channel的内部类。Unsafe中的接口操作都和JDK底层相关,包括:分配内存、Socket四元组信息、注册事件循环、绑定端口、Socket的连接和关闭、Socket的读写。

//A nexus to a network socket or a component which is capable of I/O operations such as read, write, connect, and bind.
public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {
    //Returns the globally unique identifier of this Channel.
    ChannelId id();
    
    //Return the EventLoop this Channel was registered to.
    EventLoop eventLoop();

    //Returns the parent of this channel.
    Channel parent();

    //Returns the configuration of this channel.
    ChannelConfig config();

    //Returns true if the Channel is open and may get active later
    boolean isOpen();

    //Returns true if the Channel is registered with an EventLoop.
    boolean isRegistered();

    //Return true if the Channel is active and so connected.
    boolean isActive();

    //Return the ChannelMetadata of the Channel which describe the nature of the Channel.
    ChannelMetadata metadata();

    //Returns the local address where this channel is bound to.  
    //The returned SocketAddress is supposed to be down-cast into more concrete type such as InetSocketAddress to retrieve the detailed information. 
    SocketAddress localAddress();

    //Returns the remote address where this channel is connected to.  
    //The returned SocketAddress is supposed to be down-cast into more concrete type such as InetSocketAddress to retrieve the detailed information.
    SocketAddress remoteAddress();

    //Returns the ChannelFuture which will be notified when this channel is closed.  
    //This method always returns the same future instance.
    ChannelFuture closeFuture();

    //Returns true if and only if the I/O thread will perform the requested write operation immediately.  
    //Any write requests made when this method returns false are queued until the I/O thread is ready to process the queued write requests.
    boolean isWritable();

    //Get how many bytes can be written until #isWritable() returns false.
    //This quantity will always be non-negative. If #isWritable() is false then 0.
    long bytesBeforeUnwritable();

    //Get how many bytes must be drained from underlying buffers until #isWritable() returns true.
    //This quantity will always be non-negative. If #isWritable() is true then 0.
    long bytesBeforeWritable();

    //Returns an <em>internal-use-only</em> object that provides unsafe operations.
    Unsafe unsafe();

    //Return the assigned ChannelPipeline.
    ChannelPipeline pipeline();

    //Return the assigned ByteBufAllocator which will be used to allocate ByteBufs.
    ByteBufAllocator alloc();

    @Override
    Channel read();

    @Override
    Channel flush();

    //Unsafe operations that should never be called from user-code. 
    //These methods are only provided to implement the actual transport, and must be invoked from an I/O thread except for the following methods:
    //#invoker()
    //#localAddress()
    //#remoteAddress()
    //#closeForcibly()
    //#register(EventLoop, ChannelPromise)
    //#deregister(ChannelPromise)
    //#voidPromise()
    interface Unsafe {
        //Return the assigned RecvByteBufAllocator.Handle which will be used to allocate ByteBuf's when receiving data.
        RecvByteBufAllocator.Handle recvBufAllocHandle();

        //Return the SocketAddress to which is bound local or null if none.
        SocketAddress localAddress();

        //Return the SocketAddress to which is bound remote or null if none is bound yet.
        SocketAddress remoteAddress();

        //Register the Channel of the ChannelPromise and notify the ChannelFuture once the registration was complete.
        void register(EventLoop eventLoop, ChannelPromise promise);

        //Bind the SocketAddress to the Channel of the ChannelPromise and notify it once its done.
        void bind(SocketAddress localAddress, ChannelPromise promise);

        //Connect the Channel of the given ChannelFuture with the given remote SocketAddress.
        //If a specific local SocketAddress should be used it need to be given as argument. Otherwise just pass null to it.
        //he ChannelPromise will get notified once the connect operation was complete.
        void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);

        //Disconnect the Channel of the ChannelFuture and notify the ChannelPromise once the operation was complete.
        void disconnect(ChannelPromise promise);

        //Close the Channel of the ChannelPromise and notify the ChannelPromise once the operation was complete.
        
下载前可以先看下教程 https://pan.quark.cn/s/a426667488ae 标题“仿淘宝jquery图片左右切换带数字”揭示了这是一个关于运用jQuery技术完成的图片轮播机制,其特色在于具备淘宝在线平台普遍存在的图片切换表现,并且在整个切换环节中会展示当前图片的序列号。 此类功能一般应用于电子商务平台的产品呈现环节,使用户可以便捷地查看多张商品的照片。 说明中的“NULL”表示未提供进一步的信息,但我们可以借助标题来揣摩若干核心的技术要点。 在构建此类功能时,开发者通常会借助以下技术手段:1. **jQuery库**:jQuery是一个应用广泛的JavaScript框架,它简化了HTML文档的遍历、事件管理、动画效果以及Ajax通信。 在此项目中,jQuery将负责处理用户的点击动作(实现左右切换),并且制造流畅的过渡效果。 2. **图片轮播扩展工具**:开发者或许会采用现成的jQuery扩展,例如Slick、Bootstrap Carousel或个性化的轮播函数,以达成图片切换的功能。 这些扩展能够辅助迅速构建功能完善的轮播模块。 3. **即时数字呈现**:展示当前图片的序列号,这需要通过JavaScript或jQuery来追踪并调整。 每当图片切换时,相应的数字也会同步更新。 4. **CSS美化**:为了达成淘宝图片切换的视觉效果,可能需要设计特定的CSS样式,涵盖图片的排列方式、过渡效果、点状指示器等。 CSS3的动画过渡特性(如`transition``animation`)在此过程中扮演关键角色。 5. **事件监测**:运用jQuery的`.on()`方法来监测用户的操作,比如点击左右控制按钮或自动按时间间隔切换。 根据用户的交互,触发相应的函数来执行...
垃圾实例分割数据集 一、基础信息 • 数据集名称:垃圾实例分割数据集 • 图片数量: 训练集:7,000张图片 验证集:426张图片 测试集:644张图片 • 训练集:7,000张图片 • 验证集:426张图片 • 测试集:644张图片 • 分类类别: 垃圾(Sampah) • 垃圾(Sampah) • 标注格式:YOLO格式,包含实例分割的多边形点坐标,适用于实例分割任务。 • 数据格式:图片文件 、适用场景 • 智能垃圾检测系统开发:数据集支持实例分割任务,帮助构建能够自动识别分割图像中垃圾区域的AI模型,适用于智能清洁机器人、自动垃圾桶等应用。 • 环境监控与管理:集成到监控系统中,用于实时检测公共区域的垃圾堆积,辅助环境清洁治理决策。 • 计算机视觉研究:支持实例分割算法的研究优化,特别是在垃圾识别领域,促进AI在环保方面的创新。 • 教育与实践:可用于高校或培训机构的AI课程,作为实例分割技术的实践数据集,帮助学生理解计算机视觉应用。 三、数据集优势 • 精确的实例分割标注:每个垃圾实例都使用详细的多边形点进行标注,确保分割边界准确,提升模型训练效果。 • 数据多样性:包含多种垃圾物品实例,覆盖不同场景,增强模型的泛化能力鲁棒性。 • 格式兼容性强:YOLO标注格式易于与主流深度学习框架集成,如YOLO系列、PyTorch等,方便研究人员开发者使用。 • 实际应用价值:直接针对现实世界的垃圾管理需求,为自动化环保解决方案提供可靠数据支持,具有重要的社会意义。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值