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

netty 源码之Bootstrap

 
阅读更多
Bootstrap 以及 ServerBootstrap类都继承自 AbstractBootstrap
这个抽象类很有趣,请看
public abstract class AbstractBootstrap<B extends AbstractBootstrap<?>> {
...
}

泛型中的类是自身的子类。其实如果明白这个类的作用,就知道为什么要这么写了。
见doc:
AbstractBootstrap is a helper class that makes it easy to bootstrap a  Channel. It support method-chaining to provide an easy way to configure the AbstractBootstrap
也就是说,这是一个帮助类,为了更方便启用Channel,为了方便,支持了method-chainning 也就是说函数都返回一个对自身的引用。这样我们就可以使用
instance.get().put(3).add(4)之类的写法,在NIO中很常见。

下面我们看看 AbstractBootstrap有些什么。
先看 成员变量,
public abstract class AbstractBootstrap<B extends AbstractBootstrap<?>> {
    private EventLoopGroup group;
    private ChannelFactory factory;
    private SocketAddress localAddress;
    private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>();
    private final Map<AttributeKey<?>, Object> attrs = new LinkedHashMap<AttributeKey<?>, Object>();
    private ChannelHandler handler;
}


一个事件组。netty是事件驱动的,事件组应该是各种事件的容器(猜想,因为还没看,也暂时不用在意)
一个Channel工厂,这自然是用来生产Channel的(这里应该有各种管道。比如服务端的和客户端的就不一样)
SocketAddress是本地地址
options 是这个管道的属性集合
attrs 是属性键集合(这个搞不懂,先放下)
ChannelHandler 用于处理管道的各种事件吧。
猜想到此为止。我们看看具体的功能函数吧。

1, public B group(EventLoopGroup group)
这个函数简单,设置group,注意如果传入参数为空,或者原先的group不为空都要抛出异常。然后,返回自身 ,注意泛型 B

2, public B channel(Class<? extends Channel> channelClass)
这个类用来创建一个Channel实例,使用了ChannelFactory。使用工厂模式推迟具体实例创建到子类中。这里可以看做一个工厂设置

3, public B channelFactory(ChannelFactory factory)
2调用了3,

4,public B localAddress(SocketAddress localAddress)
绑定本地地址

5, public B localAddress(int port)
同样绑定本地地址

6, public B localAddress(String host, int port)
同4,5

7, public  B localAddress(InetAddress host, int port)
通4,5,6

8, public <T> B option(ChannelOption<T> option, T value)
实例化Channel时的参数。如果 value为null,这个option被remove掉。

9, public <T> B attr(Attribute<T> key, T value)
实例化Channel后Channel的属性value为null时,attr被remove掉。

10, public void shutdown()
这里关闭的是EventLoopGroup

11, protected void validate()
这里变protected了,用于同类的参数验证。子类如果复写,需要使用super先调用父类

12,protected final void validate(ChannelFuture future)
验证了future不为null,然后调用11, 不可以被复写

13,public ChannelFuture bind()
创建一个Channel并且绑定

14,public B handler(ChannelHandler handler)
handler不能为null,设置handler

15,public static boolean ensureOpen(ChannelFuture future)
确保future中的channel为open状态,否则futrue设置为失败ChannelException

16,public abstract ChannelFuture bind(ChannelFuture future)
把Channel绑定到给定的ChannelFactory上。抽象方法,意味着需要具体的Channel

之后的方法都类似于get方法。不在一一列举。
综上所观,这个类就是一个配置类。
我们在看看具体的子类。
首先
Bootstrap类增加了InternalLogger 和SocketAddress(remoteAddress)
在抽象类中没有实现的 bind函数,这里也实现了。
  @Override
    public ChannelFuture bind(ChannelFuture future) {
        validate(future);
        if (localAddress() == null) {
            throw new IllegalStateException("localAddress not set");
        }

        try {
            init(future.channel());
        } catch (Throwable t) {
            future.setFailure(t);
            return future;
        }

        if (!ensureOpen(future)) {
            return future;
        }

        return future.channel().bind(localAddress(), future).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
    }


这段代码基本就是原始的netty的客户端使用标准。
首先,validate验证futrue,factory和group,再验证localAddress
接下来就是利用future的特性初始化channel,如果channel没有打开,那么ensureOpen是已经设置了future的失败,直接返回future,如果channel成功打开,那么绑定本地地址并且添加一个失败关闭的ChannelFutrueListener
这里,关键的是init(Channel)函数了。
init函数首先检查Channel是否是激活的,是否是注册的,是否是打开的。
然后再Channel的pipeline中加入handler,并且添加ChannelOption参数和Attribute属性
我们也看到,Channel已经不是NIO中的Channel了,她是netty的Channel,每个Channel都有ChannelPipeline,也有ChannelConfig这样的东西。记住这些,我们后面会去看他们是如何工作的。
最后,仔细看 group().register(channel).syncUninterruptibly();
这句使得我们的channel的register变成同步不可中断的。这里的注册应该是让我们的Channel成为EventLoopGroup的会员。

与bind类似的函数就是connect了。客户端的一个动作就是连接服务端。
那么connect也是和bind类似,不过要注意,bind是bind本地地址,而connect则需要的是远程地址,所以检查的时候不一样,而且connect的时候可以没有本地绑定哦。
如 future.channel().connect(remoteAddress,futrue)
同样给future设置一个监听器,当连接失败的时候关闭Channel

客户端的validate,多了一个handler的validate,如果没有会报IllegalStateException,所以也要设置handler

最后,看看 public Bootstrap channel(Class<? extends Channel> channelClass)
函数,这个函数用于设置不同的ChannelFactory来创建不同的Channel
这里,如果channelClass是AioSocketChannel,那么我们就使用AioSocketChannelFactory,否则就是默认的。

这里还内嵌了AioSocketChannelFactory,实现很简单
 private final class AioSocketChannelFactory implements ChannelFactory {
        @Override
        public Channel newChannel() {
            return new AioSocketChannel((AioEventLoopGroup) group());
        }

        @Override
        public String toString() {
            return AioSocketChannel.class.getSimpleName() + ".class";
        }
    }

所以可以看到,channel的参数如果是AioSocketChannel,则创建异步的Channel


看完了client端使用Bootstrap,我们看看ServerBootstrap
server端,多了一个InetSocketAddress 具体的IP地址。同时,有一个接受处理器:
private final ChannelHandler acceptor = new ChannelInitializer<Channel>(){
    @Override
    public void initChannel(Channel ch) throws Exception {
        ch.pipeline().addLast(new Acceptor());
    }
};


与此同时,服务端还多了一组 ChannelOption和AttributeKey,还有相应的EventLoopGroup以及ChannelHandler,这些前面都有“child”
看函数 public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup)
我们就明白了,其实这里的child就是client端的,而parent就是作为acceptor。

在channel(Class<? extends Channel> channelClass)函数中,多了一个对于channelClass是否是ServerChannel的子类。然后是channelClass是否是异步Channel,如果是则设置AioServerSocketChannelaFactory

ServerBootstrap中还可以设置child的参数选项和属性。
对于ServerBootstrap, 比较重要的是Acceptor,这个类其实处理了连接过来的Channel
rivate class Acceptor
            extends ChannelInboundHandlerAdapter implements ChannelInboundMessageHandler<Channel> {

        @Override
        public MessageBuf<Channel> newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
            return Unpooled.messageBuffer();
        }

        @Override
        public void freeInboundBuffer(ChannelHandlerContext ctx, ChannelBuf buf) throws Exception {
            // Nothing to free
        }

        @SuppressWarnings("unchecked")
        @Override
        public void inboundBufferUpdated(ChannelHandlerContext ctx) {
            MessageBuf<Channel> in = ctx.inboundMessageBuffer();
            for (;;) {
                Channel child = in.poll();
                if (child == null) {
                    break;
                }

                child.pipeline().addLast(childHandler);

                for (Entry<ChannelOption<?>, Object> e: childOptions.entrySet()) {
                    try {
                        if (!child.config().setOption((ChannelOption<Object>) e.getKey(), e.getValue())) {
                            logger.warn("Unknown channel option: " + e);
                        }
                    } catch (Throwable t) {
                        logger.warn("Failed to set a channel option: " + child, t);
                    }
                }

                for (Entry<AttributeKey<?>, Object> e: childAttrs.entrySet()) {
                    child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
                }

                try {
                    childGroup.register(child);
                } catch (Throwable t) {
                    child.unsafe().closeForcibly();
                    logger.warn("Failed to register an accepted channel: " + child, t);
                }
            }
        }
    }



很容易理解了就是得到客户端Channel后使用child的变量设置一番。

至此,我们就大概了解Bootstrap的功能了。同时也看到一点如何使用netty的影子了。
之后可以顺藤摸瓜,一窥netty的各种实现。









分享到:
评论

相关推荐

    netty源码深入分析

    《Netty源码深入分析》是由美团基础架构部的闪电侠老师所分享的一系列关于Netty源码解析的视频教程。以下将根据标题、描述、标签以及部分内容等信息,对Netty及其源码进行深入剖析。 ### Netty简介 Netty是基于...

    【项目实战】Netty源码剖析&NIO;+Netty5各种RPC架构实战演练三部曲视频教程(未加密)

    ### Netty源码剖析与NIO及Netty5各种RPC架构实战演练三部曲知识点解析 #### 一、Netty概述 Netty是一款基于Java NIO的高性能服务器端编程框架,用于快速开发可维护的网络应用程序。它简化了网络编程的复杂性,使...

    netty源码和相关中文文档

    2. **Channel**:在 Netty 中,每个连接都表示为一个 Channel,它可以读写数据,同时管理与之相关的事件。 3. **Bootstrap**:启动引导类,用于配置并创建一个新的 ServerBootstrap 或 ClientBootstrap,用于启动...

    netty源码解析视频

    ### Netty源码解析知识点概览 #### 一、Netty简介与应用场景 - **Netty**是一款由JBOSS提供的高性能的异步事件驱动的网络应用框架,用于快速开发可维护的高性能协议服务器和客户端。 - **应用场景**:Netty广泛...

    netty源码 4.*版本

    在深入探讨 Netty 源码之前,我们先了解一下 Netty 的核心概念和架构。 Netty 的主要特点包括: 1. **异步非阻塞I/O**:Netty 基于 NIO(Non-blocking I/O)库,利用了 Java 的 Channel 和 Selector,使得网络操作...

    Netty源码依赖包

    在深入探讨Netty源码依赖包的相关知识点之前,我们首先需要了解Netty的基本概念及其重要性。Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器与客户端。它提供了丰富的...

    netty源码解析视频.txt

    根据提供的文件信息,这里将对Netty源码的相关知识点进行详细解析。Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器与客户端。Netty因其优秀的性能和灵活的设计而受到...

    netty源码深入剖析.txt

    《Netty源码深入剖析》一书旨在帮助读者深入了解Netty框架的工作原理和技术细节,从基础知识入手,逐步过渡到高级优化技巧,使开发者能够更好地掌握并应用Netty于实际项目中。 ### 一、Netty简介与核心特性 Netty...

    Netty框架源码(并且有详细的注释)

    Netty是一个高性能、异步事件驱动的网络应用框架...总的来说,这个压缩包提供了一个深入学习Netty源码的机会,通过阅读和实践,开发者能够掌握Netty的设计理念,提升网络编程的能力,并能根据需求定制自己的网络框架。

    Netty源码教程-4

    在本篇Netty源码教程的第四部分,我们将深入探讨Netty框架的核心组件和工作原理,以便更好地理解和利用这个高性能、异步事件驱动的网络应用框架。Netty被广泛应用于分布式系统、高并发服务器和复杂网络协议的实现,...

    netty源码+Spring源码视频教程.txt

    ### Netty源码分析 #### 1. Netty简介 Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器与客户端。其核心设计思想是简化网络编程的复杂性,并提供高度可定制化的API,...

    netty源码分析之服务端启动全解析

    Netty是一款高性能的网络应用程序框架,它使用Java编程语言开发,主要用于网络应用程序的快速和易于开发,支持TCP和UDP...通过对Netty源码的深入分析,可以更好地理解其工作机制,对开发高性能的网络应用有极大的帮助。

    极客时间《Netty源码剖析与实战》学习记录-boy-learning-netty.zip

    在深入探讨 Netty 源码剖析与实战的学习记录之前,我们需要了解 Netty 的基本概念和核心特性。 1. **Netty 简介** - **设计理念**:Netty 的设计目标是简化网络应用的开发,提供一个高度抽象的API,让开发者可以...

    高清Netty5.0架构剖析和源码解读

    NIO客户端13 3.Netty源码分析16 3.1. 服务端创建16 3.1.1. 服务端启动辅助类ServerBootstrap16 3.1.2. NioServerSocketChannel 的注册21 3.1.3. 新的客户端接入25 3.2. 客户端创建28 3.2.1. 客户端连接辅助类...

    咕泡学院_Tom_JavaVIP课程_深入分析Netty源码1

    JavaVIP课程深入分析了Netty源码,由Tom老师主讲,主要针对咕泡学院的高级Java学员。本文档详细探讨了Netty框架的核心组件及其使用,特别关注了BootStrap类在客户端和服务器端的角色。 BootStrap是Netty提供的一种...

    netty实战源码13章

    在深入探讨 Netty 源码之前,我们先了解一下 Netty 的基本概念和架构。 Netty 提供了一种高度抽象的模型来处理网络通信,包括 TCP、UDP 和 HTTP 等多种协议。在 Netty 中,最重要的概念是 Channel(通道)和 Event...

    Netty in action 第二版 源码

    源码分析对于深入理解Netty的工作原理至关重要。 Netty的核心概念包括以下几个方面: 1. **ByteBuf**: ByteBuf是Netty中的缓冲区类,替代了Java NIO的ByteBuffer。ByteBuf提供了更高效、更安全的字节操作,并且...

Global site tag (gtag.js) - Google Analytics