netty源码解析-启动引导(1) 服务端启动流程

导读

原创文章,转载请注明出处。

本文源码地址:netty-source-code-analysis

本文所使用的netty版本4.1.6.Final:带注释的netty源码

我们在“BIO vs NIO”这篇文章中我们给出了使用jdk原生nio编写的服务端Hello World。还记得其中的关键步骤吗,咱们再来温习一下。

  1. 创建一个ServerSocketChannel

  2. 将ServerSocketChannel设置为非阻塞的

  3. 将ServerSocketChannel绑定到8000端口

  4. 将ServerSocketChannel注册到selector上

今天我们就以这几个关键步骤为目标来看一下在netty中是怎么做的,以及在这几个步骤的中间netty又多做了哪些工作。

1 服务端引导代码

以下代码引导启动一个服务端,在以下文章中我们以“引导代码”指代这段程序。这段代码很简单,创建两个EventLoopGroup分别为bossGroupworkerGroup。创建一个ServerBoostrap并将bossGroupworkerGroup传入,配置一个handler,该handler为监听端口这条连接所使用的handler。接着又设置了一个childHandler即新连接所使用的handler,本篇文章我们不讲新连接的接入,所以这里的childHandler里什么也没做。

运行这段这段代码将在控制台打出如下结果。

HandlerAdded
ChannelRegistered
ChannelActive

/**
 * 欢迎关注公众号“种代码“,获取博主微信深入交流
 *
 * @author wangjianxin
 */
public class com.zhongdaima.netty.analysis.bootstrap.ServerBoot {
   
    public static void main(String[] args) throws InterruptedException {
   
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup(1);
        try {
   
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .attr(AttributeKey.valueOf("ChannelName"), "ServerChannel")
                    .handler(new ChannelInboundHandlerAdapter() {
   
                        @Override
                        public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
   
                            System.out.println("ChannelRegistered");
                        }

                        @Override
                        public void channelActive(ChannelHandlerContext ctx) throws Exception {
   
                            System.out.println("ChannelActive");
                        }

                        @Override
                        public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
   
                            System.out.println("HandlerAdded");
                        }
                    }).childHandler(new ChannelInboundHandlerAdapter(){
   

            });
            ChannelFuture f = b.bind(8000).sync();
            f.channel().closeFuture().sync();
        } finally {
   
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

2 启动过程

我们从ChannelFuture f = b.bind(8000).sync()bind方法往下跟到AbstractBootStrapdoBind方法,这中间的过程很简单,就是将端口号封装为SocketAddress

doBind内的关键代码有第一行的initAddRegister方法,还有后面的doBind0方法。

private ChannelFuture doBind(final SocketAddress localAddress) {
   
        final ChannelFuture regFuture = initAndRegister();
        if (regFuture.isDone()) {
   
             doBind0(regFuture, channel, localAddress, promise);
        } else {
   
            
            final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
            regFuture.addListener(new ChannelFutureListener() {
   
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
   
                    Throwable cause = future.cause();
                    if (cause != null) {
   
                    } else {
   
                        doBind0(regFuture, channel, localAddress, promise);
                    }
                }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值