Netty底层也是基于NIO,所以在分析服务启动的流程之前,我们先回顾一下NIO的启动Server的代码,写的一个Server例子如下,只保留和Netty启动相关的代码
public class NioServer implements Runnable {
public static void main(String[] args) {
new Thread(new NioServer(8080)).start();
}
private Selector selector;
private ServerSocketChannel serverChannel;
public NioServer(int port) {
try {
selector = Selector.open();
serverChannel = ServerSocketChannel.open();
serverChannel.socket().bind(new InetSocketAddress(port), 1024);
serverChannel.configureBlocking(false);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e) {
}
}
public void run() {
//SelectionKey处理
}
}
构造方法里先创建Selector和ServerSocketChannel,绑定端口和地址,然后Channel设置为非阻塞, 最后将该Channel注册到Selector上,一个简单的NIO初始化代码就是这样,Netty启动的时候核心也是这个代码,只不过Netty封装了(感觉有点复杂=_=)下面会看下Netty是怎么处理的
源码分析
首先看下NettyServer的Demo(本文基于netty4.1.22版本)
public void bind(int port) {
//配置服务端的NIO线程组
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup(4);
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
.childHandler(new ChannelInitializer<SocketChannel>(){
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline()
.addLast(new NettyServerHandler());
}
});
//绑定端口,同步等待成功
ChannelFuture f = b.bind(port).sync();