1. 服务端示例代码
public class MyServer2 {
public static void main(String[] args) {
//负责接收客户端的连接请求
EventLoopGroup boosGroup = new NioEventLoopGroup(1);
//负责接收客户端读写请求
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boosGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler())
.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//解码器
pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
//编码器
pipeline.addLast(new LengthFieldPrepender(4));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
pipeline.addLast(new MyServerHandler());
// pipeline.addLast(new MyServerHandler1());
// pipeline.addLast(new MyServerHandler2());
}
});
ChannelFuture channelFuture = bootstrap.bind(9872).sync();
System.out.println("系统启动成功!!!");
channelFuture.channel().closeFuture().sync();
System.out.println("系统执行完成!!!");
} catch (Exception e) {
e.printStackTrace();
} finally {
boosGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
2. 服务器启动流程
之前说过,netty是在javaNIO的基础上,进行了相应的封装,因此,在ServerBootstrap启动的过程中,重点流程和NIO创建服务类似,包括如下几个步骤:
- 创建通道并设置为非阻塞模式。
- 向selector注册通道。
- 开启线程接收连接请求。
- 开启线程接收读写请求(启动流程中未有体现)。
注意:在启动完成时,boosEventLoopGroup会启动一个事件循环(线程),该线程会执行while(true)操作,用以处理任务和客户端连接请求。而workerGroup不会启动。只有当第一个客户端请求到来之后,才会从workerGroup中选择一个事件循环进行后续逻辑的处理。
3. 客户端访问服务器端时,服务器端执行流程
当服务端启动完成后,bossGroup中的EventLoop(线程)将会启动,并一直执行while(true)操作,并在循环中检查selector是否监控到IO准备就绪操作。
当客户端请求服务器端时,bossGroup中的EventLoop中的selector将会获取到连接IO请求,该EventLoop将会对客户端建立连接,并触发pipeline上的handler处理,在ServerBootstrapAcceptor中,会为新建立的通道添加handler,并将新建的通道注册到workerGroup中。
当把新建的通道注册到workerGroup时,其实是从workerGroup中选择一个EventLoop,然后将任务提交给该EventLoop。该workerGroup的EventLoop将进行如下三个操作:
- 实现selector和通道的注册,并激活pipeline上的相关事件,如通道添加handler、通道注册成功、激活通道等事件。
- selector将会检查客户端的读写事件,如果获取到读写事件后,会触发workerGroup中的EventLoop的pipeline上的handler操作。
- workerGroup的EventLoop执行死循环。
注意:不管是bossGroup中的EventLoop还是workerGroup中的EventLoop,都包含一个selector,且该selector可以监控N个通道的连接事件或读写事件。