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 ...
随机推荐
- python 10 else EasyGui(转载)
else语句 if else 要么怎么样,要么不怎么样 while else 干完了能怎样,干不完就不怎样 (异常处理) else 没有问题,就干吧 try: int('a') except Valu ...
- SpringMVC修改视图定位
@ 目录 什么是视图定位 修改springmvc-servlet.xml 修改IndexController 移动index.jsp 测试 什么是视图定位 如果代码写成这样,就表示跳转到页面 inde ...
- golang 判断IPv4 or IPv6 address
import strings func IsIPv4(address string) bool { return strings.Count(address, ":") < ...
- Windows中使用PowerShell查看和卸载补丁
查看:get-hotfix -id KB4470788 卸载:wusa /uninstall /kb:3045999 get-hotfix -id KB4470788 wusa /uninstall ...
- python3.6和pip3:Ubuntu下安装升级与踩坑之路
本文以Ubuntu16.x系统为例,演示如何安装python3.6和相应环境.安装Python3的机器必须要能访问外网才能进行如下操作! 1. 安装方式 在Ubuntu下安装python有两种方式: ...
- 细说强网杯Web辅助
本文首发于“合天智汇”公众号 作者:Ch3ng 这里就借由强网杯的一道题目“Web辅助”,来讲讲从构造POP链,字符串逃逸到最后获取flag的过程 题目源码 index.php 获取我们传入的user ...
- swf反编辑软件带弹窗和跳转swf文件
http://www.wocaoseo.com/thread-296-1-1.html swf反编辑有啥用,在seo上.淘客上.网赚上,只有稍微牛逼些的人恐怕无人不知.无人不晓吧,这个软件是完全免费的 ...
- csp201909-2小明种苹果续
/* 定义输入N 二维数组 输出T总数 D掉落棵树 E掉落组数 定义last记录上次掉落的编号,flag=1表示两次连续掉落,不掉落归零 spec=1表示1 2都掉落了,spec=2表示只有1掉落 对 ...
- AQI分析
A Q I 分 析 1.背景信息 AOI( Air Quality Index),指空气质量指数,用来衡量空气清洁或污染的程度.值越小,表示空气质量越好.近年来,因为环境问题,空气质量也越来越受到人 ...
- Docker 搭建 Redis Cluster 集群环境
使用 Docker 搭建 Redis Cluster,最重要的环节就是容器通信的问题,这一块我们在之前的文章中已经给大家解决了<Docker 网络模式详解及容器间网络通信>,本篇文章主要练 ...