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源码剖析与NIO及Netty5各种RPC架构实战演练三部曲知识点解析 #### 一、Netty概述 Netty是一款基于Java NIO的高性能服务器端编程框架,用于快速开发可维护的网络应用程序。它简化了网络编程的复杂性,使...
2. **Channel**:在 Netty 中,每个连接都表示为一个 Channel,它可以读写数据,同时管理与之相关的事件。 3. **Bootstrap**:启动引导类,用于配置并创建一个新的 ServerBootstrap 或 ClientBootstrap,用于启动...
### Netty源码解析知识点概览 #### 一、Netty简介与应用场景 - **Netty**是一款由JBOSS提供的高性能的异步事件驱动的网络应用框架,用于快速开发可维护的高性能协议服务器和客户端。 - **应用场景**:Netty广泛...
在深入探讨 Netty 源码之前,我们先了解一下 Netty 的核心概念和架构。 Netty 的主要特点包括: 1. **异步非阻塞I/O**:Netty 基于 NIO(Non-blocking I/O)库,利用了 Java 的 Channel 和 Selector,使得网络操作...
在深入探讨Netty源码依赖包的相关知识点之前,我们首先需要了解Netty的基本概念及其重要性。Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器与客户端。它提供了丰富的...
根据提供的文件信息,这里将对Netty源码的相关知识点进行详细解析。Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器与客户端。Netty因其优秀的性能和灵活的设计而受到...
《Netty源码深入剖析》一书旨在帮助读者深入了解Netty框架的工作原理和技术细节,从基础知识入手,逐步过渡到高级优化技巧,使开发者能够更好地掌握并应用Netty于实际项目中。 ### 一、Netty简介与核心特性 Netty...
Netty是一个高性能、异步事件驱动的网络应用框架...总的来说,这个压缩包提供了一个深入学习Netty源码的机会,通过阅读和实践,开发者能够掌握Netty的设计理念,提升网络编程的能力,并能根据需求定制自己的网络框架。
在本篇Netty源码教程的第四部分,我们将深入探讨Netty框架的核心组件和工作原理,以便更好地理解和利用这个高性能、异步事件驱动的网络应用框架。Netty被广泛应用于分布式系统、高并发服务器和复杂网络协议的实现,...
### Netty源码分析 #### 1. Netty简介 Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器与客户端。其核心设计思想是简化网络编程的复杂性,并提供高度可定制化的API,...
Netty是一款高性能的网络应用程序框架,它使用Java编程语言开发,主要用于网络应用程序的快速和易于开发,支持TCP和UDP...通过对Netty源码的深入分析,可以更好地理解其工作机制,对开发高性能的网络应用有极大的帮助。
在深入探讨 Netty 源码剖析与实战的学习记录之前,我们需要了解 Netty 的基本概念和核心特性。 1. **Netty 简介** - **设计理念**:Netty 的设计目标是简化网络应用的开发,提供一个高度抽象的API,让开发者可以...
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. 客户端连接辅助类...
JavaVIP课程深入分析了Netty源码,由Tom老师主讲,主要针对咕泡学院的高级Java学员。本文档详细探讨了Netty框架的核心组件及其使用,特别关注了BootStrap类在客户端和服务器端的角色。 BootStrap是Netty提供的一种...
在深入探讨 Netty 源码之前,我们先了解一下 Netty 的基本概念和架构。 Netty 提供了一种高度抽象的模型来处理网络通信,包括 TCP、UDP 和 HTTP 等多种协议。在 Netty 中,最重要的概念是 Channel(通道)和 Event...
源码分析对于深入理解Netty的工作原理至关重要。 Netty的核心概念包括以下几个方面: 1. **ByteBuf**: ByteBuf是Netty中的缓冲区类,替代了Java NIO的ByteBuffer。ByteBuf提供了更高效、更安全的字节操作,并且...