前文Netty源码分析系列--3. 服务器启动ServerBootStrap分析中介绍了对ServerBootStrap
的多个变量赋值后,下一步就要绑定端口号启动服务器。
ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
调用bind(8899)
进入抽象类AbstractBootStrap
的doBind
方法:
private ChannelFuture doBind(final SocketAddress localAddress) {
final ChannelFuture regFuture = initAndRegister();
final Channel channel = regFuture.channel();
if (regFuture.cause() != null) {
return regFuture;
}
if (regFuture.isDone()) {
ChannelPromise promise = channel.newPromise();
doBind0(regFuture, channel, localAddress, promise);
return promise;
} else {
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;
}
}
其中关键的方法是:
intAndRegister()
- 对
ChannelFuture
类型的对象regFuture
添加监听器,当IO操作完成时执行回调方法operationComplete
。
1 . 先关注第1行initAndRegister
方法如下:其中channelFactory.newChannel()
就是使用之前channel
方法中创建的ReflectiveChannelFactory
通过反射新建NioServerSocketChannel
实例。
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
channel = channelFactory.newChannel();
init(channel);
} catch (Throwable t) {
if (channel != null) {
// channel can be null if newChannel crashed (eg SocketException("too many open files"))
channel.unsafe().closeForcibly();
// as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
}
// as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
}
ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
NioServerSocketChannel
类的构造函数:静态变量DEFAULT_SELECTOR_PROVIDER
使用了NIO Selector Provider,构造函数中调用静态方法newSocket
。
使用
provider.openServerSocketChannel()
创建NioServerSocketChannel
。
private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
private static ServerSocketChannel newSocket(SelectorProvider provider) {
try {
return provider.openServerSocketChannel();
} catch (IOException e) {
throw new ChannelException(
"Failed to open a server socket.", e);
}
}
public NioServerSocketChannel() {
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
2. initAndRegister
中使用ChannelFactory
创建完Channel
后,调用了init
进行初始化。
void init(Channel channel) throws Exception {
//以上省略......
ChannelPipeline p = channel.pipeline();
final EventLoopGroup currentChildGroup = childGroup;
final ChannelHandler currentChildHandler = childHandler;
//省略部分代码......
p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(final Channel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline();
ChannelHandler handler = config.handler();
if (handler != null) {
pipeline.addLast(handler);
}
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
}
获得channel
对象的pipleline
,如果有配置handler
对象如LoggingHandler(LogLevel.INFO)
,会加入到pipeline
中。
注意:这里出现了一个类
ServerBootstrapAcceptor
,稍后会介绍。
3. initAndRegister
中:
ChannelFuture regFuture = config().group().register(channel);
上面代码group()
获得bossGroup
对象,并将channel
注册到该EventLoopGroup
。