一、前言
上篇简单分析了下future、promise,由于这个在netty源码中用的实在太多,不得不提前了解下,这篇就开始分析源码了,先从server端开始~~~
二、源码分析
首先简单贴下server端的代码,这里只贴了核心代码
public void startServer() throws Exception {
// 只监听一个端口,因此只需要设置成线程数为1即可
EventLoopGroup boss = new NioEventLoopGroup(1);
EventLoopGroup worker = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(boss, worker);
// 底层实现1、首先创建ReflectiveChannelFactory2、调用反射机制创建
// NioServerSocketChannel,同时还会创建pipeline,默认创建DefaultChannelPipeline
b.channel(NioServerSocketChannel.class);
b.childHandler(nettyTelnetInitializer);
// 服务器绑定端口监听,bind()操作异步的
ChannelFuture f = b.bind(SERVER_PORT);
// 这个函数将会调用ChannelInitializer的initChannel(ChannelHandlerContext)方法
// 只有在这个方法执行之后,server才算是绑定了端口
f = f.sync();
// 监听服务器关闭监听
f.channel().closeFuture().sync();
} finally {
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
在startServer()方法中,首先创建了两个NioEventLoopGroup类,由于netty是基于reactor线程模型的,这里两个类也分别代表boss和workers。(至于什么是reactor线程模型,下下篇再介绍吧)
紧接着创建ServerBootstrap调用group()方法,
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
super.group(parentGroup);
if (childGroup == null) {
throw new NullPointerException("childGroup");
}
if (this.childGroup != null) {
throw new IllegalStateException("childGroup set already");
}
this.childGroup = childGroup;
return this;
}
@SuppressWarnings("unchecked")
public B group(EventLoopGroup group) {
if (group == null) {
throw new NullPointerException("group");
}
if (this.group != null) {
throw new IllegalStateException("group set already");
}
this.group = group;
return (B) this;
}
再然后设置channel,由于是服务的,因此设置NioServerSocketChannel,底层源码
public B channel(Class extends C> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
}
return channelFactory(new ReflectiveChannelFactory(channelClass));
}
public B channelFactory(ChannelFactory extends C> channelFactory) {
if (channelFactory == null) {
throw new NullPointerException("channelFactory");
}
if (this.channelFactory != null) {
throw new IllegalStateException("channelFactory set already");
}
this.channelFactory = channelFactory;
return (B) this;
}
由此可见,默认ChannelFactory是ReflectiveChannelFactory。再看它的构造函数
// 这里的clazz很明显就是NioServerSocketChannel,主要为了后面的反射使用
public ReflectiveChannelFactory(Class extends T> clazz) {
if (clazz == null) {
throw new NullPointerException("clazz");
}
this.clazz = clazz;
}
设置完一些参数之后之后,接着就是注册和绑定了.绑定操作在AbstractBootstrap的doBind()
private ChannelFuture doBind(final SocketAddress localAddress) {
// 初始化channel和注册channel,都是异步操作
final ChannelFuture regFuture = initAndRegister();
// 获取channel
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();
doBind0(regFuture, channel, localAddress, promise);
return promise;
} else {
// Registration future is almost always fulfilled already, but just in case it's not.
final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
// 为Future添加一个监听器,当Future完成之后调用该方法,同时,当该方法执行之后,将会
// 调用sync()方法中的wait()之后的代码
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();
// 开始绑定ip和端口号
doBind0(regFuture, channel, localAddress, promise);
}
}
});
return promise;
}
}
// 初始化和注册
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
// 通过反射创建channel
channel = channelFactory.newChannel();
// 初始化channel
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);
}
// 注册channel
ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
//ServerBootstrap类执行初始化
@Override
void init(Channel channel) throws Exception {
final Map, Object> options = options0();
synchronized (options) {
setChannelOptions(channel, options, logger);
}
final Map, Object> attrs = attrs0();
synchronized (attrs) {
for (Entry, Object> e: attrs.entrySet()) {
@SuppressWarnings("unchecked")
AttributeKey
ok,到这里,channel的初始化和注册都完成了,DefaultChannelPromise,接着我们看最后一个方法吧.
// 此时的f是:DefaultChannelPromise的子类:PendingRegistrationPromise
f = f.sync()
//DefaultChannelPromise类
@Override
public ChannelPromise sync() throws InterruptedException {
super.sync();
return this;
}
//DefaultPromise类
@Override
public Promise sync() throws InterruptedException {
await();
rethrowIfFailed();
return this;
}
这里的await方法比较重要,我们看源码,前面的不重要,最重要的是wait()方法,这个是object的方法,也就是说到了这里它会
进入"睡眠"状态,直到future 完成.这个我们可以在
@Override
public Promise await() throws InterruptedException {
if (isDone()) {
return this;
}
if (Thread.interrupted()) {
throw new InterruptedException(toString());
}
checkDeadLock();
synchronized (this) {
while (!isDone()) {
incWaiters();
try {
wait();
} finally {
decWaiters();
}
}
}
return this;
}
三、总结
本来准备客户端服务放在一起分析的,不过可能占用篇幅过大,就分成两篇了.
总的来说,server端过程如下:
1、初始化channel
2、NioEventLoop类的regist()方法,将channel注册到selector
3、同步,就是调用sync()方法,该方法必须调用
虽然总结的比较简单,但是源码还是挺复杂的.
下篇就就分析client端的了~