在前两篇博客中我们分别介绍了NioEventLoopGroup
的创建过程和ServerBootstarp
的创建的过程前面的准备的过程都已经结束了。是时候启动我们的服务端了,打开我们熟悉的代码,具体的代码如下:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
//服务端
public class NettyServer {
public static void main(String[] args) throws InterruptedException {
//就是一个死循环,不停地检测IO事件,处理IO事件,执行任务
//创建一个线程组:接受客户端连接 主线程
EventLoopGroup bossGroup = new NioEventLoopGroup(1);//cpu核心数*2
//创建一个线程组:接受网络操作 工作线程
EventLoopGroup workerGroup = new NioEventLoopGroup(); //cpu核心数*2
//是服务端的一个启动辅助类,通过给他设置一系列参数来绑定端口启动服务
ServerBootstrap serverBootstrap = new ServerBootstrap();
// 我们需要两种类型的人干活,一个是老板,一个是工人,老板负责从外面接活,
// 接到的活分配给工人干,放到这里,bossGroup的作用就是不断地accept到新的连接,将新的连接丢给workerGroup来处理
serverBootstrap.group(bossGroup, workerGroup)
//设置使用NioServerSocketChannel作为服务器通道的实现
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128) //设置线程队列中等待连接的个数
.childOption(ChannelOption.SO_KEEPALIVE, true)//保持活动连接状态
//表示服务器启动过程中,需要经过哪些流程,这里NettyTestHandler最终的顶层接口为ChannelHandler,
// 是netty的一大核心概念,表示数据流经过的处理器
.handler(new NettyTestHendler())
//表示一条新的连接进来之后,该怎么处理,也就是上面所说的,老板如何给工人配活
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
nioSocketChannel.pipeline().addLast(new StringDecoder(), new NettyServerHendler());
}
});
System.out.println(".........server init..........");
// 这里就是真正的启动过程了,绑定9090端口,等待服务器启动完毕,才会进入下行代码
ChannelFuture future = serverBootstrap.bind(9090).sync();
System.out.println(".........server start..........");
//等待服务端关闭socket
future.channel().closeFuture().sync();
// 关闭两组死循环
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
今天我们主要分析的是serverBootstrap.bind(9090)
方法,让我们点开对应的源码,一探究竟,看看服务端是如何启动,具体的代码如下:
public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
public ChannelFuture bind(int inetPort) {
//根据传入的端口号,创建一个本地的IP地址+端口号传入到bind()方法中去
return bind(new InetSocketAddress(inetPort));
}
public ChannelFuture bind(SocketAddress localAddress) {
//判断 group channelFactory 对象不为空 serverBootstrap.group serverBootstrap.channel 已经设置
validate();
//ObjectUtil.checkNotNull(localAddress, "localAddress") 还是返回的localAddress对象 判断不为空
//继续调用diBind()方法
return doBind(ObjectUtil.checkNotNull(localAddress, "localAddress"));
}
//这儿校验对应的group和channelFactory是否已经设置好
public B validate() {
//group是NioEventLoopGroup,就是我们上篇博客中提到的有很多属性的对象
if (group == null) {
throw new IllegalStateException("group not set");
}
//channelFactory对应的NioServerSocketChannel.class的工厂类,对应的有两个参数,上篇博客也有说到
if (channelFactory == null) {
throw new IllegalStateException("channel or channelFactory not set");
}
return self();
}
//这个方法就是整个服务端启动的流程,我们要一点点的分析
private ChannelFuture doBind(final SocketAddress localAddress) {
//初始化和注册
//走来进入的initAndRegister()的方法
final ChannelFuture regFuture = initAndRegister();
final Channel channel = regFuture.channel();
if (regFuture.cause() != null) {
return regFuture;
}
if (regFuture.isDone()) {
// At this point we know that the registration was complete and successful.
ChannelPromise promise = channel.newPromise();
doBind0(regFuture, channel, localAddress, promise);
return promise;
} else {
// Registration future is almost always fulfilled already, but just in case it's not.
final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
regFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
Throwable cause = future.cause();
if (cause != null) {
promise.setFailure(cause);
} else {
promise.registered();
doBind0(regFuture, channel, localAddress, promise);
}
}
});
return promise;
}
}
}
上面的方法,就是绑定了一个IP地址+端口号,同时进行相应的校验,校验group
和channelFactory
是否为空,因为我们前面已经设置了,所以这儿不可能为空,所以调用对应doBind()
方法,当打开对应的方法,发现方法很长,所以我们这儿要一点点到分析,走来执行的initAndRegister();
方法。我们打开对应的代码,如下:
public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
//通过反射创建NioServerSocketChannel
//channelFactory=new ReflectiveChannelFactory ---> constructor=NioServerSocketChannel.class.getConstructor();
//channel=NioServerSocketChannel
//走来先调用channelFactory.newChannel();的方法
channel = channelFactory.newChannel();
init(channel);
} catch (Throwable t) {
if (channel != null) {
channel.unsafe().closeForcibly();
return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
}
return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
}
//config().group()==bossGroup ===> EventLoopGroup bossGroup=new NioEventLoopGroup(1);
//register开启了事件轮询线程
//config().group() boosGroup
ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
}
上面的代码我们发现走来的调用channelFactory.newChannel();
的方法,我们在上一篇博客讲ServerBootstrap
初始化的过程的时候,我们知道这个channelFactory
属性对应的NioServerSocketChannel.class.getConstructor()
,而newChannel()
就是调用NioServerSocketChannel
的构造函数,我们打开对应类的构造函数,具体的代码如下:
public class NioServerSocketChannel extends AbstractNioMessageChannel
implements io.netty.channel.socket.ServerSocketChannel {
public NioServerSocketChannel() {
//newSocket(DEFAULT_SELECTOR_PROVIDER)返回 ServerSocketChannel
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
//创建的是java nio中ServerSocketChannel
private static ServerSocketChannel newSocket(SelectorProvider provider) {
try {
/**
* 使用{@link SelectorProvider}打开{@link SocketChannel},从而删除条件in
* 否则,每个ServerSocketChannel.open()将调用{@link SelectorProvider#provider()}。
*
* See <a href="https://github.com/netty/netty/issues/2308">#2308</a>.
*/
return provider.openServerSocketChannel();
} catch (IOException e) {
throw new ChannelException(
"Failed to open a server socket.", e);
}
}
public NioServerSocketChannel(ServerSocketChannel channel) {
//调用对应的父类的构造函数
super(null, channel, SelectionKey.OP_ACCEPT);
//javaChannel()==> serverSocketChannel
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
}
我们发现调用NioServerSocketChannel
的构造函数函数,创建了一个java
原生的ServerSocketChannel
,然后调用父类的构造函数,我们继续跟进去,查看对应的代码,具体的代码如下:
public abstract class AbstractNioMessageChannel extends AbstractNioChannel {
//传入进来的parent = null
//ch = java 原生的ServerSocketChannel
//readInterestOp = SelectionKey.OP_ACCEPT 注册事件
protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
//parent --> null
//ch--> serverSocketChannel 服务端channel
//readInterestOp--->SelectionKey.OP_ACCEPT
//调用对应的父类的构造函数
super(parent, ch, readInterestOp);
}
}
当我们打开对应的函数发现调用的是父类的对应的构造函数,所以我们继续跟进父类的构造函数,打开对应的构造函数如下:
public abstract class AbstractNioChannel extends AbstractChannel {
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
//parent ---> null
//ch ---> serverSocketChannel 服务器channel java 原生的ServerSocketChannel
//readInterestOp ---> SelectionKey.OP_ACCEPT 注册事件
//继续调用对应的父类的构造函数
super(parent);
this.ch = ch;
this.readInterestOp = readInterestOp;
try {
ch.configureBlocking(false);
} catch (IOException e) {
try {
ch.close();
} catch (IOException e2) {
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to close a partially initialized socket.", e2);
}
}
throw new ChannelException("Failed to enter non-blocking mode.", e);
}
}
}
当我们打开父类的构造函数,发现调用的还是父类的构造函数,我们继续打开对应的父类的构造函数,具体代码如下:
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
protected AbstractChannel(Channel parent) {
//parent = null
this.parent = parent;
id = newId();
//读写都和这个对象有关
unsafe = newUnsafe();
//创建对应的ChannelPipeline()
pipeline = newChannelPipeline();
}
}
我们发现打开对应的父类的构造函数,主要操作时对parent进行对应的赋值,然后创建id进行对应的赋值,unsafe和pipeline同样时进行创建赋值。我们先打开newId()
对应的代码如下:
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
protected ChannelId newId() {
return DefaultChannelId.newInstance();
}
}
当我们打开对应的创建ID的方法,发现是继续调用对应的创建ID的函数,最终点进去,我们发现就是随机生成ID。至于生成规则我们不需要做过多的了解。你只需要知道这个ID是用来作为channel的标示字段,具有唯一性,有点像数据库中的主键。我们看完了创建ID的过程,我们继续查看创建Unsafe
接口的实现类的过程。由于Unsafe
接口的实现类的过程比较复杂,我们就查看一下Unsafe
接口中的方法,打开对应的代码如下:
interface Unsafe {
//当接收到数据,将用于分配ByteBuf
RecvByteBufAllocator.Handle recvBufAllocHandle();
//返回绑定到本地的socketAddress,如果没有则返回null
SocketAddress localAddress();
//返回绑定到远程的socketAddress,如果没有则返回null
SocketAddress remoteAddress();
//注册ChannelPromise的Channel,并在注册完成后通知ChannelFuture
void register(EventLoop eventLoop, ChannelPromise promise);
//将SocketAddress绑定到ChannelPromise的Channel,并在完成后通知
void bind(SocketAddress localAddress, ChannelPromise promise);
//将给定的ChannelFuture的Channel与给定的远程SocketAddress连接。
//如果应使用特定的本地SocketAddress,则需要将其作为参数。否则,只需
//将null传递给它。连接操作完成后,ChannelPromise将会收到通知。
void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);
//操作完成后,断开ChannelFuture的Channel并通知ChannelPromise
void disconnect(ChannelPromise promise);
//操作完成后,关闭ChannelPromise的Channel并通知ChannelPromise
void close(ChannelPromise promise);
//立即关闭Channel而不触发任何事件。可能仅在注册尝试失败时有用。
void closeForcibly();
//从EventLoop中注销ChannelPromise的Channel,并在操作完成后通知ChannelPromise
void deregister(ChannelPromise promise);
//调度读取操作,该操作将填充ChannelPipeline中第一个ChannelInboundHandler的入站缓冲区。
//如果已经有一个待处理的读取操作,则此方法不执行任何操作。
void beginRead();
//写操作
void write(Object msg, ChannelPromise promise);
//清除通过ChannelPromise安排的所有写操作。
void flush();
//返回一个特殊的ChannelPromise,可以重复使用并将其传递给Unsafe中的操作。
//永远不会通知它成功或错误,所以它只是一个占位符以ChannelPromise为参数但您不想被通知的操作。
ChannelPromise voidPromise();
//返回Channel的ChannelOutboundBuffer,存储未决的写请求。
ChannelOutboundBuffer outboundBuffer();
}
可以看到Unsafe
接口的类主要处理的读写,一些连接的事件的处理。看完了unsafe
属性的赋值,最后让我们看看创建pipeline
的过程,具体代码如下:
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
protected AbstractChannel(Channel parent) {
//parent = null
this.parent = parent;
id = newId();
//读写都和这个对象有关
unsafe = newUnsafe();
//创建对应的ChannelPipeline()
pipeline = newChannelPipeline();
}
}
我们去查看对应的pipeline
的创建过程。具体的代码如下:
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
protected DefaultChannelPipeline newChannelPipeline() {
//this-->NioServerSocketChannel
return new DefaultChannelPipeline(this);
}
}
我们可以看到调用的DefaultChannelPipeline
的构造函数,传入的参数是NioServerSocketChannel
这个时候我们打开DefaultChannelPipeline
的构造函数,具体的代码如下:
public class DefaultChannelPipeline implements ChannelPipeline {
//传入的参数是NioServerSocketChannel
protected DefaultChannelPipeline(Channel channel) {
this.channel = ObjectUtil.checkNotNull(channel, "channel");
succeededFuture = new SucceededChannelFuture(channel, null);
voidPromise = new VoidChannelPromise(channel, true);
//创建尾结点
tail = new TailContext(this);
//创建头节点 头节点中维护了AbstractChannel中unsafe对象
head = new HeadContext(this);
head.next = tail;
tail.prev = head;
}
}
可以发现上面的代码就是进行对应的赋值操作,赋值完的DefaultChannelPipeline
如下图所示:
创建好的DefaultChannelPipeline
的对象如上图所示,我们再来看看TailContext
和HeadContext
的创建过程,具体的代码如下:
final class TailContext extends AbstractChannelHandlerContext implements ChannelInboundHandler {
TailContext(DefaultChannelPipeline pipeline) {
//调用父类的构造函数
super(pipeline, null, TAIL_NAME, TailContext.class);
//设置添加完成
setAddComplete();
}
}
final class HeadContext extends AbstractChannelHandlerContext
implements ChannelOutboundHandler, ChannelInboundHandler {
private final Unsafe unsafe;
HeadContext(DefaultChannelPipeline pipeline) {
//调用父类的构造函数
super(pipeline, null, HEAD_NAME, HeadContext.class);
unsafe = pipeline.channel().unsafe();
//设置添加完成
setAddComplete();
}
}
两个对象的创建都是调用父类的构造函数,具体的代码如下:
abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {
AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor,
String name, Class<? extends ChannelHandler> handlerClass) {
//pipeline=DefaultChannelPipeline
//executor=null
//name =没传系统默认创建
//handler=TailContext.class
this.name = ObjectUtil.checkNotNull(name, "name");
this.pipeline = pipeline;
this.executor = executor;
this.executionMask = mask(handlerClass);
ordered = executor == null || executor instanceof OrderedEventExecutor;
}
}
创建好的AbstractChannelHandlerContext
如下图所示:
我们执行AbstractChannelHandlerContext
创建完成后,我们通过CAS
设置成添加完成了。至此newChannelPipeline()
创建完成了,最后我们再看下对应的代码,具体如下:
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
protected AbstractChannel(Channel parent) {
//parent = null
this.parent = parent;
id = newId();
//读写都和这个对象有关
unsafe = newUnsafe();
//创建对应的ChannelPipeline()
pipeline = newChannelPipeline();
}
}
至此AbstractChannel
类创建完成,具体的AbstractChannel
类如下图所示:
父类AbstractChannel
创建完成了,我们回到AbstractNioChannel
继续执行下面的代码,具体的代码如下:
public abstract class AbstractNioChannel extends AbstractChannel {
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
//parent --> null
//ch--> serverSocketChannel 服务器channel
//readInterestOp--->SelectionKey.OP_ACCEPT
//创建id,unsafe pipeline
//执行完父类的构造函数返回了,继续往下执行赋值操作
super(parent);
this.ch = ch;
this.readInterestOp = readInterestOp;
try {
//设置成非阻塞
ch.configureBlocking(false);
} catch (IOException e) {
try {
ch.close();
} catch (IOException e2) {
if (logger.isWarnEnabled()) {
logger.warn(
"Failed to close a partially initialized socket.", e2);
}
}
throw new ChannelException("Failed to enter non-blocking mode.", e);
}
}
}
这个时候AbstractNioChannel
类的图如下所示:
这个时候AbstractNioChannel
初始化完成了,返回到原来的调用的地方,具体的代码如下:
public class NioServerSocketChannel extends AbstractNioMessageChannel
implements io.netty.channel.socket.ServerSocketChannel {
public NioServerSocketChannel(ServerSocketChannel channel) {
//调用完成后返回,继续执行下面的代码
super(null, channel, SelectionKey.OP_ACCEPT);
//javaChannel()==> serverSocketChannel
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
}
可以看到我们又创建了一个对象NioServerSocketChannelConfig(this, javaChannel().socket());
传入的参数的当前对象,和javaChannel().socket()
两个参数,由于是同样是赋值操作,我直接在下面用代码表示
public class NioServerSocketChannel extends AbstractNioMessageChannel
implements io.netty.channel.socket.ServerSocketChannel {
private final class NioServerSocketChannelConfig extends DefaultServerSocketChannelConfig {
private NioServerSocketChannelConfig(NioServerSocketChannel channel, ServerSocket javaSocket) {
// channel --> NioServerSocketChannel
//javaSocket==> serverSocketChannel.socket() 服务端channel nio api
//一样调用的是父类的构造函数
super(channel, javaSocket);
}
}
}
public class DefaultServerSocketChannelConfig extends DefaultChannelConfig
implements ServerSocketChannelConfig {
public DefaultServerSocketChannelConfig(ServerSocketChannel channel, ServerSocket javaSocket) {
// channel --> NioServerSocketChannel
//javaSocket==> serverSocketChannel.socket() 服务端channel nio api
//一样调用的是父类的构造函数进行赋值
super(channel);
if (javaSocket == null) {
throw new NullPointerException("javaSocket");
}
this.javaSocket = javaSocket;
}
}
public class DefaultChannelConfig implements ChannelConfig {
public DefaultChannelConfig(Channel channel) {
// channel --> NioServerSocketChannel
this(channel, new AdaptiveRecvByteBufAllocator());
}
protected DefaultChannelConfig(Channel channel, RecvByteBufAllocator allocator) {
// channel --> NioServerSocketChannel
//allocator 预测器
setRecvByteBufAllocator(allocator, channel.metadata());
this.channel = channel;
}
}
可以看到上面的一连串的操作,都是赋值的操作,将传入的NioServerSocketChannel
赋值给DefaultChannelConfig
的channel
属性,将serverSocketChannel.socket()
赋值给DefaultServerSocketChannelConfig
的javaSocket
的属性。到此NioServerSocketChannel
初始化就完成了,同时将刚才创建好的NioServerSocketChannelConfig
对象赋值给当前类的config
的属性。至此channelFactory.newChannel()
方法就执行完成,我们继续返回到原来的代码继续查看剩下的代码,具体的代码如下:
public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
//初始化并注册
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
//通过反射创建NioServerSocketChannel
//channelFactory=new ReflectiveChannelFactory ---> constructor=NioServerSocketChannel.class.getConstructor();
//channel=NioServerSocketChannel
//将创建好NioServerSocketChannel类赋值给该类的channel属性,继续执行剩下的代码
channel = channelFactory.newChannel();
//接下来执行下面的方法
init(channel);
} catch (Throwable t) {
if (channel != null) {
channel.unsafe().closeForcibly();
return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
}
return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
}
//config().group()==bossGroup ===> EventLoopGroup bossGroup=new NioEventLoopGroup(1);
//register开启了事件轮询线程
//config().group() boosGroup
ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
}
上面的channelFactory.newChannel();
执行完将对应的对象返回到对应的属性channel
中去,然后执行对应的init(channel);
的方法,我们打开init(channel);
方法,具体的代码如下:
public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel> {
@Override
void init(Channel channel) throws Exception {
//channel=NioServerSocketChannel
//options0 获取的是用户自己设置的tcp参数 ServerBootstrap.option(ChannelOption.SO_BACKLOG,128)
final Map<ChannelOption<?>, Object> options = options0();
synchronized (options) {
//设置用户设置的tcp参数
setChannelOptions(channel, options, logger);
}
//attrs0() ServerBootstrap.attr() 获取用户设置的attr参数
final Map<AttributeKey<?>, Object> attrs = attrs0();
synchronized (attrs) {
for (Entry<AttributeKey<?>, Object> e : attrs.entrySet()) {
@SuppressWarnings("unchecked")
AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
channel.attr(key).set(e.getValue());
}
}
//channel=NioServerSocketChannel
//获取AbstractChannel.pipeline();的pipeline(DefaultChannelPipeline)
ChannelPipeline p = channel.pipeline();
//这儿获取的之前初始化的NioEvetLoopGroup
final EventLoopGroup currentChildGroup = childGroup;
//自己传入进来的Channelhandler 默认继承或者间接继承ChanelHandler
final ChannelHandler currentChildHandler = childHandler;
final Entry<ChannelOption<?>, Object>[] currentChildOptions;
final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
//将传入的参数设置到当前的option属性中
synchronized (childOptions) {
currentChildOptions = childOptions.entrySet().toArray(newOptionArray(0));
}
//将传入的参数设置到当前的attr属性中
synchronized (childAttrs) {
currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(0));
}
p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(final Channel ch) throws Exception {
//System.out.println(ch==channel); true
final ChannelPipeline pipeline = ch.pipeline();
//System.out.println(pipeline==p); true
//config.handler()=自己创建的new ChannelInitializer<ServerSocketChannel>()
ChannelHandler handler = config.handler();
if (handler != null) {
pipeline.addLast(handler);
}
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
//System.out.println("执行了");
//bossGroup将客户端连接转交给workerGroup
pipeline.addLast(
new ServerBootstrapAcceptor(ch, currentChildGroup,
currentChildHandler, currentChildOptions,currentChildAttrs));
}
});
}
});
}
}
将之前的设置好的options
,attrs
设置到传入的NioServerSocketChannel
将对应的参数进行对应的赋值,然后执行addLast()
的方法,具体的代码如下:
public class DefaultChannelPipeline implements ChannelPipeline {
@Override
public final ChannelPipeline addLast(ChannelHandler... handlers) {
//handlers=new ChannelInitializer<Channel>
return addLast(null, handlers);
}
@Override
public final ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) {
if (handlers == null) {
throw new NullPointerException("handlers");
}
for (ChannelHandler h: handlers) {
if (h == null) {
break;
}
//executor = null
//name = null
//h = new ChannelInitializer<Channel>
addLast(executor, null, h);
}
return this;
}
@Override
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
//group=null
//name =null
//handler=new ChannelInitializer<Channel>
final AbstractChannelHandlerContext newCtx;
synchronized (this) {
//检查添加
checkMultiplicity(handler);
//filterName(name, handler) 当我们没有指定名字时 给我们默认生成一个
//new DefaultChannelHandlerContext()
newCtx = newContext(group, filterName(name, handler), handler);
addLast0(newCtx);
if (!registered) {
//判断handlerState属性等于0 并且设置为1
newCtx.setAddPending();
callHandlerCallbackLater(newCtx, true);
return this;
}
//返回NioEvenGroup
EventExecutor executor = newCtx.executor();
if (!executor.inEventLoop()) {
callHandlerAddedInEventLoop(newCtx, executor);
return this;
}
}
callHandlerAdded0(newCtx);
return this;
}
private static void checkMultiplicity(ChannelHandler handler) {
if (handler instanceof ChannelHandlerAdapter) {
ChannelHandlerAdapter h = (ChannelHandlerAdapter) handler;
//没有加这个注解同时又是单例的对象,下面直接会抛异常
if (!h.isSharable() && h.added) {
throw new ChannelPipelineException(
h.getClass().getName() +
" is not a @Sharable handler, so can't be added or removed multiple times.");
}
h.added = true;
}
}
}
上面的函数进行一连串的链式调用,最终调用到对应的方法,走来是执行checkMultiplicity()
这儿,当添加的对象没有加对应的@ChannelHandler.Sharable
注解,同时又是一个单例对象,这个时候就表示重复添加了。会直接报错。然后会调用对应的newContext(EventExecutorGroup group, String name, ChannelHandler handler)
方法,具体的代码如下:
public class DefaultChannelPipeline implements ChannelPipeline {
private AbstractChannelHandlerContext newContext(EventExecutorGroup group, String name,
ChannelHandler handler) {
//group=null
//name =没传系统默认创建
//handler=new ChannelInitializer<Channel>
return new DefaultChannelHandlerContext(this, childExecutor(group), name, handler);
}
}
上面的代码创建了一个DefaultChannelHandlerContext
对象,我们继续跟进去,看创建的对象是什么样的,具体的代码如下:
final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext {
DefaultChannelHandlerContext(
DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) {
//pipeline=DefaultChannelPipeline
//executor=null
//name =没传系统默认创建
//handler=new ChannelInitializer<Channel>
super(pipeline, executor, name, handler.getClass());
//此Handler是ChannelInitializer
this.handler = handler;
}
}
当我们打开对应的代码发现,和之前创建头尾的节点是一致的。这个时候,我们就理解了。我们继续回到我们之前调用的代码的处,具体的代码如下:
public class DefaultChannelPipeline implements ChannelPipeline {
@Override
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
//group=null
//name =null
//handler=new ChannelInitializer<Channel>
final AbstractChannelHandlerContext newCtx;
synchronized (this) {
//检查添加
checkMultiplicity(handler);
//filterName(name, handler) 当我们没有指定名字时 给我们默认生成一个
//new DefaultChannelHandlerContext()
newCtx = newContext(group, filterName(name, handler), handler);
//执行如下对应的代码。
addLast0(newCtx);
if (!registered) {
//判断handlerState属性等于0 并且设置为1
newCtx.setAddPending();
callHandlerCallbackLater(newCtx, true);
return this;
}
//返回NioEvenGroup
EventExecutor executor = newCtx.executor();
if (!executor.inEventLoop()) {
callHandlerAddedInEventLoop(newCtx, executor);
return this;
}
}
callHandlerAdded0(newCtx);
return this;
}
}
我们发现执行完了创建newContext
方法过后,将创建好的DefaultChannelHandlerContext
对象赋值给newCtx
属性,然后调用addLast0(newCtx);
方法,具体的代码如下:
public class DefaultChannelPipeline implements ChannelPipeline {
private void addLast0(AbstractChannelHandlerContext newCtx) {
//newCtx=new DefaultChannelHandlerContext()
AbstractChannelHandlerContext prev = tail.prev;
newCtx.prev = prev;
newCtx.next = tail;
prev.next = newCtx;
tail.prev = newCtx;
}
}
我们发现将我们创建好的DefaultChannelHandlerContext
对象添加对应的队列中去。这个时候构建出来的是我们前面创建好的匿名内部类ChannelInitializer
至此addLast0()
执行完成,这个时候,返回到原来的方法。具体如下:
public class DefaultChannelPipeline implements ChannelPipeline {
@Override
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
//group=null
//name =null
//handler=new ChannelInitializer<Channel>
final AbstractChannelHandlerContext newCtx;
synchronized (this) {
//检查添加
checkMultiplicity(handler);
//filterName(name, handler) 当我们没有指定名字时 给我们默认生成一个
//new DefaultChannelHandlerContext()
newCtx = newContext(group, filterName(name, handler), handler);
addLast0(newCtx);
//默认registered是false,这个if是
if (!registered) {
//判断handlerState属性等于0 并且设置为1
newCtx.setAddPending();
callHandlerCallbackLater(newCtx, true);
return this;
}
//返回NioEvenGroup
EventExecutor executor = newCtx.executor();
if (!executor.inEventLoop()) {
callHandlerAddedInEventLoop(newCtx, executor);
return this;
}
}
callHandlerAdded0(newCtx);
return this;
}
}
上面的if判断是直接可以进的,因为registered
的没有改变过,默认是false
,所以这个if判断是可以进入的,然后执行if判断中两个方法,具体的代码如下:
abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {
final void setAddPending() {
//通过CAS操作将HANDLER_STATE_UPDATER从INIT改成ADD_PENDING
//将状态改成添加待处理
boolean updated = HANDLER_STATE_UPDATER.compareAndSet(this, INIT, ADD_PENDING);
assert updated;
}
}
上面的代码主要改的是传进来的对象的状态从INIT
改成ADD_PENDING
,接下来,我们继续查看 callHandlerCallbackLater(newCtx, true);
方法的代码,具体的代码如下:
public class DefaultChannelPipeline implements ChannelPipeline {
private void callHandlerCallbackLater(AbstractChannelHandlerContext ctx, boolean added) {
assert !registered;
//传入进来added等于true,所以执行的new PendingHandlerAddedTask(ctx)
PendingHandlerCallback task = added ? new PendingHandlerAddedTask(ctx) : new PendingHandlerRemovedTask(ctx);
PendingHandlerCallback pending = pendingHandlerCallbackHead;
if (pending == null) {
pendingHandlerCallbackHead = task;
} else {
// Find the tail of the linked-list.
while (pending.next != null) {
pending = pending.next;
}
pending.next = task;
}
}
}
上面传进来的added
为true
,所以执行的是new PendingHandlerAddedTask(ctx)
我们继续跟进去看看,具体的代码如下:
private final class PendingHandlerAddedTask extends PendingHandlerCallback {
PendingHandlerAddedTask(AbstractChannelHandlerContext ctx) {
super(ctx);
}
}
private abstract static class PendingHandlerCallback implements Runnable {
final AbstractChannelHandlerContext ctx;
PendingHandlerCallback next;
PendingHandlerCallback(AbstractChannelHandlerContext ctx) {
this.ctx = ctx;
}
}
最终发现就是给对应属性ctx
进行赋值。同时它还实现了Runnable
接口,由于我们的pendingHandlerCallbackHead
走来是空的,所以会将我们刚创建的PendingHandlerAddedTask(ctx)
赋值给pendingHandlerCallbackHead
,至此addLast
方法执行完成。我们返回到原来调用addLast
方法地方去,继续跟进我们的代码。
public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
//初始化并注册
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
//通过反射创建NioServerSocketChannel
//channelFactory=new ReflectiveChannelFactory ---> constructor=NioServerSocketChannel.class.getConstructor();
//channel=NioServerSocketChannel
//将创建好NioServerSocketChannel类赋值给该类的channel属性,继续执行剩下的代码
channel = channelFactory.newChannel();
//初始化channel完毕,继续执行下面的方法
init(channel);
} catch (Throwable t) {
if (channel != null) {
channel.unsafe().closeForcibly();
return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
}
return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
}
//config().group()==bossGroup ===> EventLoopGroup bossGroup=new NioEventLoopGroup(1);
//register开启了事件轮询线程
//config().group() boosGroup
ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
}
上面的init(channel);
初始化完毕后,我们再来看看NioServerSocketChannel
是什么样的,具体如下图:
至此初始化和赋值NioServerSocketChannel
就此结束,我会在下一篇博客介绍注册方法config().group().register(channel);