前文Netty源碼分析系列--3. 服務(wù)器啟動ServerBootStrap分析中介紹了對ServerBootStrap
的多個變量賦值后发绢,下一步就要綁定端口號啟動服務(wù)器。
ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
調(diào)用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;
}
}
其中關(guān)鍵的方法是:
intAndRegister()
- 對
ChannelFuture
類型的對象regFuture
添加監(jiān)聽器锌俱,當(dāng)IO操作完成時執(zhí)行回調(diào)方法operationComplete
毫胜。
1 . 先關(guān)注第1行initAndRegister
方法如下:其中channelFactory.newChannel()
就是使用之前channel
方法中創(chuàng)建的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
類的構(gòu)造函數(shù):靜態(tài)變量DEFAULT_SELECTOR_PROVIDER
使用了NIO Selector Provider,構(gòu)造函數(shù)中調(diào)用靜態(tài)方法newSocket
伦连。
使用
provider.openServerSocketChannel()
創(chuàng)建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
創(chuàng)建完Channel
后钳垮,調(diào)用了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
中。
注意:這里出現(xiàn)了一個類
ServerBootstrapAcceptor
移斩,稍后會介紹肚医。
3. initAndRegister
中:
ChannelFuture regFuture = config().group().register(channel);
上面代碼group()
獲得bossGroup
對象,并將channel
注冊到該EventLoopGroup
向瓷。