NOTE
1. Creating the Server
bind, channelFactory, and creation of NioServerSocketChannel
This is a historical learning note and may contain outdated or incomplete understanding.
bind
Start from this line and trace bind:
ChannelFuture future = bootstrap.bind(8000).sync();
Eventually execution reaches io.netty.bootstrap.AbstractBootstrap#doBind:
private ChannelFuture doBind(final SocketAddress localAddress) {
final ChannelFuture regFuture = initAndRegister();// this line
final Channel channel = regFuture.channel();
.....
}
initAndRegister
final ChannelFuture initAndRegister() {
Channel channel = null;
//..
// Call channelFactory.newChannel to create the channel.
// We need to determine which channelFactory this is.
channel = channelFactory.newChannel();
init(channel);
//...
return regFuture;
}
channel
To determine which channelFactory is used, go back to this code:
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup,workerGroup)
.channel(NioServerSocketChannel.class)// key point
io.netty.bootstrap.AbstractBootstrap#channel
public B channel(Class<? extends C> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
}
// This method assigns channelFactory to ReflectiveChannelFactory.
return channelFactory(new ReflectiveChannelFactory<C>(channelClass));
}
From the code above, we know that the factory used by channelFactory.newChannel() is ReflectiveChannelFactory, and the server-startup channelClass is NioServerSocketChannel.class.
First look at its newChannel method.
io.netty.channel.ReflectiveChannelFactory#newChannel
public T newChannel() {
try {
// Use reflection to invoke the no-argument constructor,
// which is NioServerSocketChannel here.
return clazz.getConstructor().newInstance();
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}
Create NioServerSocketChannel
- Constructor
public NioServerSocketChannel() {
// newSocket uses the JDK provider.openServerSocketChannel() underneath.
// Then it calls the parameterized constructor.
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
public NioServerSocketChannel(ServerSocketChannel channel) {
// Call the AbstractNioMessageChannel parent constructor.
// AbstractNioMessageChannel then calls the AbstractNioChannel parent constructor.
super(null, channel, SelectionKey.OP_ACCEPT);
// Configuration class used to configure options and other settings.
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
AbstractNioChannel
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
// Call AbstractChannel.
// Both clients and servers implement it.
super(parent);
this.ch = ch;
this.readInterestOp = readInterestOp;
try {
ch.configureBlocking(false);// configure NIO as non-blocking
} 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);
}
}
AbstractChannel
protected AbstractChannel(Channel parent) {
this.parent = parent;
id = newId();// channelId
unsafe = newUnsafe();// Unsafe class used to interact with low-level JDK NIO APIs
pipeline = newChannelPipeline();// create the pipeline
}
Discussion
Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub