Netty的版本是4.1.22
我们从ServerBootstrap的bind()方法开始跟踪Netty服务端的启动过程。大致分为以下四步:
- 创建NioServerSocketChannel
- 初始化NioServerSocketChannel
- 注册
- 地址绑定
一:创建NioServerSocketChannel
AbstractBootStrap
public ChannelFuture bind(String inetHost, int inetPort) {
return bind(SocketUtils.socketAddress(inetHost, inetPort));
}
public ChannelFuture bind(SocketAddress localAddress) {
validate();
if (localAddress == null) {
throw new NullPointerException("localAddress");
}
return doBind(localAddress);
}
private ChannelFuture doBind(final SocketAddress localAddress) {
final ChannelFuture regFuture = initAndRegister(); // 初始化并注册
......
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
channel = channelFactory.newChannel();
......
跟踪来到AbstractBootStrap
的initAndRegister(),它调用channelFactory的newChannel来创建channel,那么channelFactory是?在服务端会有这样的代码bootstrap.channel(NioServerSocketChannel.class)
,指定服务端要创建的channel类型为NioServerSocketChannel
,跟踪该方法会发现答案
AbstractBootStrap:
public B channel(Class<? extends C> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
}
return channelFactory(new ReflectiveChannelFactory<C>(channelClass));
}
继续往下跟踪你会发现这么一句this.channelFactory = channelFactory;
即channelFactory 指向ReflectiveChannelFactory
。
来看看 ReflectiveChannelFactory#newChannel()
的实现
@Override
public T newChannel() {
try {
return clazz.getConstructor().newInstance();
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}
反射得到 NioServerSocketChannel
实例。
接下来进入到NioServerSocketChannel
来看看它的初始化做了什么
private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER
= SelectorProvider.provider();
public NioServerSocketChannel() {
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
public NioServerSocketChannel(ServerSocketChannel channel) {
super(null, channel, SelectionKey.OP_ACCEPT);
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
先来看看 newSocket() 方法:创建一个java.nio.channels.ServerSocketChannel
private static ServerSocketChannel newSocket(SelectorProvider provider) {
try {
return provider.openServerSocketChannel();
} catch (IOException e) {
throw new ChannelException(
"Failed to open a server socket.", e);
}
}
//package sun.nio.ch;
public ServerSocketChannel openServerSocketChannel() throws IOException {
return new ServerSocketChannelImpl(this);
}
回到构造函数,还创建了NioServerSocketChannelConfig
实例,它是tcp的参数配置类。
通过super(null, channel, SelectionKey.OP_ACCEPT)
往上。注意这里SelectionKey.OP_ACCEPT,将会在之后 NioServerSocketChannel 注册到selector时监听该事件
AbstractNioMessageChannel:
protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent, ch, readInterestOp);
}
继续往上
AbstractNioChannel:
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {