// Configure the server. EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); final EchoServerHandler serverHandler = new EchoServerHandler(); try { //初始化一个服务端引导类 ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) //设置线程组 .channel(NioServerSocketChannel.class)//设置ServerSocketChannel的IO模型 分为epoll与Nio .option(ChannelOption.SO_BACKLOG, 100)//设置option参数,保存成一个LinkedHashMap, Object>() .handler(new LoggingHandler(LogLevel.INFO))//这个hanlder 只专属于 ServerSocketChannel 而不是 SocketChannel。 .childHandler(new ChannelInitializer() { //这个handler 将会在每个客户端连接的时候调用。供 SocketChannel 使用。@Override br/>@Override ChannelPipeline p = ch.pipeline(); if (sslCtx != null) { p.addLast(sslCtx.newHandler(ch.alloc())); } //p.addLast(new LoggingHandler(LogLevel.INFO)); p.addLast(serverHandler); } });
// Start the server. 启动服务
ChannelFuture f = b.bind(PORT).sync();
// Wait until the server socket is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down all event loops to terminate all threads.
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
接下来我们主要从服务端的socket在哪里初始化与哪里accept连接这两个问题入手对netty服务端启动的流程进行分析;
@Override public T newChannel() { try { return clazz.getConstructor().newInstance();//反射创建 } catch (Throwable t) { throw new ChannelException("Unable to create Channel from class " + clazz, t); } }
public B channel(Class channelClass) { if (channelClass == null) { throw new NullPointerException("channelClass"); } return channelFactory(new ReflectiveChannelFactory(channelClass)); }
Create a new instance */ public NioServerSocketChannel() { this(newSocket(DEFAULT_SELECTOR_PROVIDER));//传入默认的SelectorProvider }
private static ServerSocketChannel newSocket(SelectorProvider provider) {
try {
/**
* Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
* {@link SelectorProvider#provider()} which is called by each ServerSocketChannel.open() otherwise.
*
* See #2308.
*/
return provider.openServerSocketChannel();//可以看到创建的是jdk底层的ServerSocketChannel
} catch (IOException e) {
throw new ChannelException(
"Failed to open a server socket.", e);
}
}
第二步是通过NioServerSocketChannelConfig配置服务端Channel的构造函数,在代码中我们可以看到我们把NioServerSocketChannel这个类传入到了NioServerSocketChannelConfig的构造函数中进行配置
/**
Create a new instance using the given {@link ServerSocketChannel}. */ public NioServerSocketChannel(ServerSocketChannel channel) { super(null, channel, SelectionKey.OP_ACCEPT);//调用父类构造函数,传入创建的channel config = new NioServerSocketChannelConfig(this, javaChannel().socket()); }
@param parent the parent {@link Channel} by which this instance was created. May be {@code null}
@param ch the underlying {@link SelectableChannel} on which it operates
@param readInterestOp the ops to set to receive data from the {@link SelectableChannel} */ protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) { super(parent); this.ch = ch;//这个ch就是传入的通过jdk创建的Channel this.readInterestOp = readInterestOp; try { 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-blocking mode.", e);
}
}
第四步调用AbstractChannel这个抽象类的构造函数设置Channel的id(每个Channel都有一个id,唯一标识),unsafe(tcp相关底层操作),pipeline(逻辑链)等,而不管是服务的Channel还是客户端的Channel都继承自这个抽象类,他们也都会有上述相应的属性。我们看下AbstractChannel的构造函数
/**
Creates a new instance.
@param parent
the parent of this channel. {@code null} if there's no parent. */ protected AbstractChannel(Channel parent) { this.parent = parent; id = newId();//创建Channel唯一标识 unsafe = newUnsafe();//netty封装的TCP 相关操作类 pipeline = newChannelPipeline();//逻辑链 }