netty-example 最简单的demo 服务端启动
服务端启动 DEMO 代码
public final class DiscardClient {
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", "8009"));
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
} else {
sslCtx = null;
}
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
public void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
if (sslCtx != null) {
p.addLast(sslCtx.newHandler(ch.alloc()));
}
p.addLast(new DiscardServerHandler());
}
});
// Bind and start to accept incoming connections.
ChannelFuture f = b.bind(PORT).sync();
// Wait until the server socket is closed.
// In this example, this does not happen, but you can do that to gracefully
// shut down your server.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
/**
* Handles a server-side channel.
*/
public class DiscardServerHandler extends SimpleChannelInboundHandler<Object> {
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
// discard
}
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Close the connection when an exception is raised.
cause.printStackTrace();
ctx.close();
}
}
上面是服务端启动的简单代码,下面描述下15到35行代码发生了什么
发生了啥
new NioEventLoopGroup()
- 初始化了 EventExecutor[] children 为 CPU核心数量 * 2个 NioEventLoop实例,
- 默认每个NioEventLoop包含 一个 线程工厂(DefaultThreadFactory),创建出来的线程类型为:FastThreadLocalThread
- 默认初始化了选择器为 SelectorProvider.provider()
- 选择器工作策略。默认是 DefaultSelectStrategyFactory.INSTANCE
- 默认线程池拒绝策略,RejectedExecutionHandlers.reject()
- 默认初始化了 EventExecutorChooser chooser 为 PowerOfTwoEventExecutorChooser
- 给每一个 NioEventLoop 增加正常关闭的监听
new ServerBootstrap();
.group:设置group和childGroup
.channel:设置服务端channel的实例类型 ,方面后续bind时候反射创建NioServerSocketChannel实例
.handler:设置了客户端管道初始化handler,初始化了 ServerBootstrap 继承 AbstractBootstrap 中的 handler
.childHandler:设置了childHandler,初始化了ServerBootstrap 中的 childHandler
.bind:绑定SocketAddress(服务端的地址)
- 反射创建NioServerSocketChannel实例
- SelectorProvider.provider()构建出对应的ServerSocketChannelImpl
- 分配id
- 创建对应的unsafe实例
- 初始化pipeline
- 固定头节点
- 固定尾节点
- 设置监听事件 readInterestOp 为 SelectionKey.OP_ACCEPT
- 设置为非阻塞
- 配置 NioServerSocketChannelConfig
- 设置缓冲区内存分配器 rcvBufAllocator 为 ServerChannelRecvByteBufAllocator
- init
- 设置用户设置的channelOptions和attributes
- 初始化pipeline
- 向添加最后添加一个ChannelInitializer
- 第一步设置group中,的EventExecutorChooser chooser 选择一个 EventLoop
- EventLoop 创建一个 DefaultChannelPromise
- promise.channel().unsafe().register(this, promise);
- 通过promise然后拿到channel然后拿到unsafe实例然后
- register发生了什么
- 将NioEventLoop 保存到serverChannel
- 向刚注册的NioEventLoop提交register,将NioServerSocketChannel注册到group中
- 返回注册任务关联的ChannelFuture
- 向ChannelFuture添加addListener