netty之bootstrap
转载自https://blog.csdn.net/zxhoo/article/details/17419229
Netty4学习笔记(2)-- Bootstrap
Netty4的代码比我想象的要复杂的多,不过Netty4很好的将这种复杂性隐藏了起来,暴露出来的,是一个相对容易使用的接口。Bootstrap就是Netty试图隐藏这种复杂性的一个例子。
bootstrap包
bootstrap包是Netty4代码里最简单的一个包,总共只有4个类:
Bootstrap继承结构
AbstractBootstrap是抽象类,有两个具体的实现,Bootstrap和ServerBootstrap:
Bootstrap例子
Netty4自带的例子里有一个EchoClient,看看它是如何使用Bootstrap启动一个客户端程序的:
public class EchoClient {
private final String host;
private final int port;
private final int firstMessageSize;
public EchoClient(String host, int port, int firstMessageSize) {
this.host = host;
this.port = port;
this.firstMessageSize = firstMessageSize;
}
public void run() throws Exception {
// Configure the client.
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
//new LoggingHandler(LogLevel.INFO),
new EchoClientHandler(firstMessageSize));
}
});
// Start the client.
ChannelFuture f = b.connect(host, port).sync();
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down the event loop to terminate all threads.
group.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
// ...
}
}
Builder模式?
看上面的例子,Bootstrap的使用很像Builder模式,Bootstrap就是Builder,EventLoopGroup、Channel和Handler等是各种Part。稍有不同的是,准备好各种Part后,并不是直接build出一个Product来,而是直接通过connect()方法使用这个Product。
AbstractBootstrap
为了弄清楚Bootstrap如何工作,我们先从AbstractBootstrap入手:
public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
private volatile EventLoopGroup group;
private volatile ChannelFactory<? extends C> channelFactory;
private volatile SocketAddress localAddress;
private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>();
private final Map<AttributeKey<?>, Object> attrs = new LinkedHashMap<AttributeKey<?>, Object>();
private volatile ChannelHandler handler;
// ...
}
可以看到,AbstractBootstrap这个抽象Builder一共需要有6个Part,如下图所示:
设置各个Part
AbstractBootstrap有一组方法用来设置各个Part,例如下面这些:
public B group(EventLoopGroup group)
public B channel(Class<? extends C> channelClass)
public B channelFactory(ChannelFactory<? extends C> channelFactory)
public B localAddress(SocketAddress localAddress)
public <T> B option(ChannelOption<T> option, T value)
public <T> B attr(AttributeKey<T> key, T value)
public B handler(ChannelHandler handler)
还有一组对应方法获得各个Part,如下:
final SocketAddress localAddress()
final ChannelFactory<? extends C> channelFactory()
final ChannelHandler handler()
public final EventLoopGroup group()
final Map<ChannelOption<?>, Object> options()
final Map<AttributeKey<?>, Object> attrs()
ChannelFactory
AbstractBootstrap通过ChannelFactory创建Channel实例,channel(channelClass)方法看起来好像是设置了一个Channel,但实际上只是设置了默认的ChannelFactory实现:
public B channel(Class<? extends C> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
}
return channelFactory(new BootstrapChannelFactory<C>(channelClass));
}
默认的ChannelFactory实现使用反射创建Channel实例:
private static final class BootstrapChannelFactory<T extends Channel> implements ChannelFactory<T> {
private final Class<? extends T> clazz;
BootstrapChannelFactory(Class<? extends T> clazz) {
this.clazz = clazz;
}
@Override
public T newChannel() {
try {
return clazz.newInstance();
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}
}
Bootstrap.connect()
再来看Bootstrap类的connect()方法:
public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) {
if (remoteAddress == null) {
throw new NullPointerException("remoteAddress");
}
validate();
return doConnect(remoteAddress, localAddress);
}
connect()方法调用validate()方法看各个Part是否准备就绪,然后调用doConnect()方法:
private ChannelFuture doConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
final ChannelFuture regFuture = initAndRegister();
final Channel channel = regFuture.channel();
if (regFuture.cause() != null) {
return regFuture;
}
final ChannelPromise promise = channel.newPromise();
if (regFuture.isDone()) {
doConnect0(regFuture, channel, remoteAddress, localAddress, promise);
} else {
regFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
doConnect0(regFuture, channel, remoteAddress, localAddress, promise);
}
});
}
return promise;
}
doConnect()方法首先调用了initAndRegister()方法,然后又调用了doConnect0()方法,方法调用示意图如下:
AbstractBootstrap.initAndRegister()
final ChannelFuture initAndRegister() {
final Channel channel = channelFactory().newChannel();
try {
init(channel);
} catch (Throwable t) {
channel.unsafe().closeForcibly();
return channel.newFailedFuture(t);
}
ChannelPromise regPromise = channel.newPromise();
group().register(channel, regPromise);
// ...
}
initAndRegister()方法用ChannelFactory创建了一个Channel的实例,然后调用init()方法初始化Channel,最后将Channel注册到EventLoopGroup上:
而Channel在实例化的时候已经自动关联了Pipeline,这点从AbstractChannel的构造函数可以看出:
protected AbstractChannel(Channel parent) {
this.parent = parent;
unsafe = newUnsafe();
pipeline = new DefaultChannelPipeline(this);
}
Bootstrap.init()方法
void init(Channel channel) throws Exception {
ChannelPipeline p = channel.pipeline();
p.addLast(handler());
// ...
}
Bootstrap.init()方法把Handler添加到了Pipeline的末尾,到这里,Channel就准备就绪了:
继续Bootstrap.doConnect()
initAndRegister()方法结束之后,doConnect()方法紧接着调用了doConnect0()方法,doConnect0()方法继而调用了Channel.connect()方法,这样Channel就接通服务器,可以收发消息了!
---------------------
作者:zxh0
来源:CSDN
原文:https://blog.csdn.net/zxhoo/article/details/17419229
版权声明:本文为博主原创文章,转载请附上博文链接!
netty之bootstrap的更多相关文章
- 【Netty】(5)源码 Bootstrap
[Netty]5 源码 Bootstrap 上一篇讲了AbstractBootstrap,为这篇做了个铺垫. 一.概述 Bootstrap 是 Netty 提供的一个便利的工厂类, 我们可以通过它来完 ...
- RPC框架motan: 通信框架netty之Netty4Client
上文已经初步探讨了如何实现一个具体的transport,本文就来讨论一个具体的transport,本文讨论netty4的的相关实现.老规矩,看看motan-transport的目录结构. 其中最重要的 ...
- Netty(RPC高性能之道)原理剖析
转载:http://blog.csdn.net/zhiguozhu/article/details/50517551 1,Netty简述 Netty 是一个基于 JAVA NIO 类库的异步通信框架, ...
- 新手入门:目前为止最透彻的的Netty高性能原理和框架架构解析
1.引言 Netty 是一个广受欢迎的异步事件驱动的Java开源网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端. 本文基于 Netty 4.1 展开介绍相关理论模型,使用场景,基本组件 ...
- Netty断线重连
Netty断线重连 最近使用Netty开发一个中转服务,需要一直保持与Server端的连接,网络中断后需要可以自动重连,查询官网资料,实现方案很简单,核心思想是在channelUnregistered ...
- Netty心跳机制
一.概念介绍网络中的接收和发送数据都是使用操作系统中的SOCKET进行实现.但是如果此套接字已经断开,那发送数据和接收数据的时候就一定会有问题.可是如何判断这个套接字是否还可以使用呢?这个就需要在系统 ...
- netty ------------ 如果selector检测到一个channel可以读了
-----------------一个NioEventLoopGroup 的初始化的时候,会初始化一个 NioEventLoop数组,每个NioEventLoop在初始化的时候,会open一个sele ...
- 看 Netty 在 Dubbo 中如何应用
目录: dubbo 的 Consumer 消费者如何使用 Netty dubbo 的 Provider 提供者如何使用 Netty 总结 前言 众所周知,国内知名框架 Dubbo 底层使用的是 Net ...
- Java网络编程和NIO详解9:基于NIO的网络编程框架Netty
Java网络编程和NIO详解9:基于NIO的网络编程框架Netty 转自https://sylvanassun.github.io/2017/11/30/2017-11-30-netty_introd ...
随机推荐
- AVL树旋转
什么是AVL树? AVL树是带有平衡条件的二叉查找树,一颗AVL树首先是二叉查收树(每个节点如果有左子树或右子树,那么左子树中数据小于该节点数据,右子树数据大于该节点数据),其次,AVL树必须满足平衡 ...
- Arraylist的源码学习
@ 目录 ArrayList简介 ArrayList核心源码 ArrayList源码分析 System.arraycopy()和Arrays.copyOf()方法 两者联系与区别 ArrayList ...
- 第6章 运行Spark SQL CLI
第6章 运行Spark SQL CLI Spark SQL CLI可以很方便的在本地运行Hive元数据服务以及从命令行执行查询任务.需要注意的是,Spark SQL CLI不能与Thrift JDBC ...
- circos pipeline
# /usr/bin/env python# coding=utf-8#################################### Author : yunkeli# Version : ...
- 2020.5.27 第七篇 Scrum冲刺博客
Team:银河超级无敌舰队 Project:招新通 项目冲刺集合贴:链接 目录 一.每日站立会议 1.1 会议照片 1.2 项目完成情况 二.项目燃尽图 三.签入记录 3.1 代码/文档签入记录 3. ...
- IDEA报错:Class JavaLaunchHelper is implemented in both
在IDEA运行一个程序时报错: Class JavaLaunchHelper is implemented in both 这个错误是Mac下Java 的一个bug,意思是这个JavaLaunchHe ...
- Kubernetes入门(一)——Kubernetes v1.18.5 安装部署
Kubernetes的安装有两种方式:一是使用各个厂商封装的Kubernetes发行版,优点是可以一键安装部署,操作简单,缺点也很明显,若安装过程中某一步骤出现问题,很难定位处理:二是使用官方提供的k ...
- HP Probook 4230s 更换 CPU 过程
HP Probook 4230s 更换 CPU 过程 原来使用的 CPU 是 i5-2540M 更换为 i7-2760QM 1.松开 硬盘线 硬盘线插头上有一片黑色的胶片,可以用来拔起插头 硬盘 ...
- python练习 - 系统基本信息获取(sys标准库)+ 二维数据表格输出(tabulate库)
系统基本信息获取 描述 获取系统的递归深度.当前执行文件路径.系统最大UNICODE编码值等3个信息,并打印输出. ...
- 《我想进大厂》之mysql夺命连环13问
想进大厂,mysql不会那可不行,来接受mysql面试挑战吧,看看你能坚持到哪里? 1. 能说下myisam 和 innodb的区别吗? myisam引擎是5.1版本之前的默认引擎,支持全文检索.压缩 ...