本文将对Netty服务端中的bind方法进行分析,该方法是Netty核心的实现,通过本文你将了解Netty是怎样接收请求和处理请求的。
1.bind(…)方法
- 之前的文章已经介绍过ServerBootstrap 和相关的方法,这里主要分析的是bind()方法
ServerBootstrap bootstrap = new ServerBootstrap();
# 绑定端口
bootstrap.bind(9000).sync();
- 这里开始分析主流程,bind()方法里面最后会调用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()) {
// At this point we know that the registration was complete and successful.
ChannelPromise promise = channel.newPromise();
# 2.绑定端口的实现
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();
# 3.绑定端口的实现
doBind0(regFuture, channel, localAddress, promise);
}
}
});
return promise;
}
}
2. final ChannelFuture regFuture = initAndRegister()
- 接下来我们分析下 initAndRegister()方法干了什么事情,主要分为下面三大步骤
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
# 1.创建一个channel
channel = channelFactory.newChannel();
# 2.初始化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);
}
# 3.将channel注册到选择器selector上
ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
2.1 channel = channelFactory.newChannel()
- newChannel方法中是通过反射来创建服务端的socket,前面的文章分析过bootstrap.channel(NioServerSocketChannel.class),通过该方法创建了NioServerSocketChannel,这里的newChannel实例化了这个类,默认是调用的空构造器
public T newChannel() {
try {
# 反射得到NioServerSocketChannel对象
return constructor.newInstance();
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + constructor.getDeclaringClass(), t);
}
}
- 实例化NioServerSocketChannel对象
public NioServerSocketChannel() {
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
# 我们跟到this方法里面,直接到核心部分,如下
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
# 这个方法下面分析
super(parent);
this.ch = ch;
# 这里的readInterestOp 其实是连接事件=》SelectionKey.OP_ACCEPT
this.readInterestOp = readInterestOp;
try {
# 我们说Netty是对NIO的封装,这里可以看到NIO中的代码,设置为非阻塞
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-bl