个人笔记之Netty源码

持续更新...

此笔记为个人学习netty源码后记录所得,如有错漏烦请见谅;

学习资源B站:黑马程序员Netty全套教程,全网最全Netty深入浅出教程,Java网络编程的王者_哔哩哔哩_bilibili

 

一、启动流程

1.new InetSocketAddress()

    根据ip和端口创建SocketAddress对象,当我们只穿了端口没传ip时,这里获取当前主机的ip;

    /**
     * ServerBootstrap.bind();服务器绑定端口
     */   
    public ChannelFuture bind(int inetPort) {
        return bind(new InetSocketAddress(inetPort));
    }

    public InetSocketAddress(int port) {
        this(InetAddress.anyLocalAddress(), port);
    }

    static InetAddress anyLocalAddress() {
        return impl.anyLocalAddress();
    }

    ipv4:
        public synchronized InetAddress anyLocalAddress() {
        if (anyLocalAddress == null) {
            anyLocalAddress = new Inet4Address(); // {0x00,0x00,0x00,0x00}
            anyLocalAddress.holder().hostName = "0.0.0.0";
        }
        return anyLocalAddress;
        }

    ipv6:
        public synchronized InetAddress anyLocalAddress() {
        if (anyLocalAddress == null) {
            if (InetAddress.preferIPv6Address) {
                anyLocalAddress = new Inet6Address();
                anyLocalAddress.holder().hostName = "::";
            } else {
                anyLocalAddress = (new Inet4AddressImpl()).anyLocalAddress();
            }
        }
        return anyLocalAddress;
    }

    public InetSocketAddress(InetAddress addr, int port) {
        holder = new InetSocketAddressHolder(
                        null,
                        addr == null ? InetAddress.anyLocalAddress() : addr,
                        checkPort(port));
    }

2.init & register regFuture 处理

    final ChannelFuture initAndRegister() {
        Channel channel = null;
        try {
            // 2.1.1这个channelFactory就是我们构建BootStrape时传的NioServerSocketChannel.class
            channel = channelFactory.newChannel();
            // 2.1.2 初始化channel
            init(channel);
        } catch (Throwable t) {
            if (channel != null) {
                channel.unsafe().closeForcibly();
                return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
            }

            return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
        }

        // 2.2 register
        ChannelFuture regFuture = config().group().register(channel);
        if (regFuture.cause() != null) {
            if (channel.isRegistered()) {
                channel.close();
            } else {
                channel.unsafe().closeForcibly();
            }
        }

        return regFuture;
    }

        2.1 init

                2.1.1 创建NioSeverSocketChannel

                   channelFactory.newChannel()一路看下去,最终使用的时NioServerSocketChannel的构造方法创建的,与ServerSocketChannel.open()一样;

    // 上面的channelFactory.newChannel()最终使用的是这个构造方法
    public NioServerSocketChannel() {
        SelectorProvider.provider();
    }

                2.1.2 添加NioServerSocketChannel初始化handler

                  向ServerSocketChannel添加初始化的handler并等待调用,如acceptor handler(在accept事件发生后建立连接);ps:这里的handler都是在事件发生后才调用的,如事件不发生则不会触发;

 @Override
    void init(Channel channel) {
        setChannelOptions(channel, newOptionsArray(), logger);
        setAttributes(channel, newAttributesArray());

        ChannelPipeline p = channel.pipeline();

        final EventLoopGroup currentChildGroup = childGroup;
        final ChannelHandler currentChildHandler = childHandler;
        final Entry<ChannelOption<?>, Object>[] currentChildOptions = newOptionsArray(childOptions);
        final Entry<AttributeKey<?>, Object>[] currentChildAttrs = newAttributesArray(childAttrs);

        p.addLast(new ChannelInitializer<Channel>() {
            @Override
            public void initChannel(final Channel ch) {
                final ChannelPipeline pipeline = ch.pipeline();
                // 启动时这个handler是空的
                ChannelHandler handler = config.handler();
                if (handler != null) {
                    pipeline.addLast(handler);
                }

                ch.eventLoop().execute(new Runnable() {
                    @Override
                    public void run() {
                        // 添加一个acceptorhandler,等待accept事件触发后调用
                        pipeline.addLast(new ServerBootstrapAcceptor(
                                ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
                    }
                });
            }
        });
    }

        2.2 register

               2.2.1 通过AtomicInteger自增再与执行器求模轮询处理

    @Override
    public ChannelFuture register(Channel channel) {
        return next().register(channel);
    }


    private final AtomicInteger idx = new AtomicInteger();
    private final EventExecutor[] executors;
    @Override
    public EventExecutor next() {
        return executors[idx.getAndIncrement() & executors.length - 1];
    }

                2.2.2 register

                        启动nio boss线程;

                        原生ssc注册至selector未关注事件;

                        执行NioServerSocketChannel初始化handler;

 @Override
        public final void register(EventLoop eventLoop, final ChannelPromise promise) {
            // 判断是否已注册
            if (isRegistered()) {
                return;
            }
            // 判断eventLoop是否属于NioEventLoop
            if (!isCompatible(eventLoop)) {
                return;
            }

            AbstractChannel.this.eventLoop = eventLoop;

            // 如果当前线程已绑定eventLoop,那么直接使用当前线程执行,启动流程这里为false
            if (eventLoop.inEventLoop()) {
                register0(promise);
            } else {
                try {
                    // 启动一个新的线程(nio boss)
                    eventLoop.execute(new Runnable() {
                        @Override
                        public void run() {
                            register0(promise);
                        }
                    });
                } catch (Throwable t) {
                    closeForcibly();
                    closeFuture.setClosed();
                    safeSetFailure(promise, t);
                }
            }
        }

        private void register0(ChannelPromise promise) {
            try {
                boolean firstRegistration = neverRegistered;
                // 原生ssc注册到selector未关注事件
                doRegister();
                neverRegistered = false;
                registered = true;
                // 执行NioServerSocketChannel初始化handler(不包括我们构建BootStrap注册进来的事件)
                pipeline.invokeHandlerAddedIfNeeded();

                safeSetSuccess(promise);
                pipeline.fireChannelRegistered();
                if (isActive()) {
                    if (firstRegistration) {
                        pipeline.fireChannelActive();
                    } else if (config().isAutoRead()) {
                        beginRead();
                    }
                }
            } catch (Throwable t) {
            }
        }

    @Override
    protected void doRegister() throws Exception {
        boolean selected = false;
        for (;;) {
            try {
                selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
                return;
            } catch (CancelledKeyException e) {
                
            }
        }
    }

    private void callHandlerAddedForAllHandlers() {
        final PendingHandlerCallback pendingHandlerCallbackHead;
        synchronized (this) {
            assert !registered;
            registered = true;
            pendingHandlerCallbackHead = this.pendingHandlerCallbackHead;
            this.pendingHandlerCallbackHead = null;
        }

        PendingHandlerCallback task = pendingHandlerCallbackHead; // DefaultChannelPipeline$PendingHandlerAddedTask
        while (task != null) {
            task.execute();
            task = task.next;
        }
    }

3.regFuture

        3.1 原生ServerSocketChannel绑定

    private static void doBind0(
            final ChannelFuture regFuture, final Channel channel,
            final SocketAddress localAddress, final ChannelPromise promise) {
        channel.eventLoop().execute(new Runnable() {
            @Override
            public void run() {
                if (regFuture.isSuccess()) {
                    channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
                } else {
                    promise.setFailure(regFuture.cause());
                }
            }
        });
    }

    @Override
    public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) {
        final AbstractChannelHandlerContext next = findContextOutbound(MASK_BIND);
        EventExecutor executor = next.executor();
        if (executor.inEventLoop()) {
            // 启动流程已经绑定了eventLoop
            next.invokeBind(localAddress, promise);
        } else {
            safeExecute(executor, new Runnable() {
                @Override
                public void run() {
                    next.invokeBind(localAddress, promise);
                }
            }, promise, null, false);
        }
        return promise;
    }

    @SuppressJava6Requirement(reason = "Usage guarded by java version check")
    @Override
    protected void doBind(SocketAddress localAddress) throws Exception {
        // bind最终走到这里,根据java版本确认bing方法
        if (PlatformDependent.javaVersion() >= 7) {
            javaChannel().bind(localAddress, config.getBacklog());
        } else {
            javaChannel().socket().bind(localAddress, config.getBacklog());
        }
    }

        3.2 触发NioServerSocketChannel active事件

    private void invokeChannelActive() {
        if (invokeHandler()) {
            try {
                ((ChannelInboundHandler) handler()).channelActive(this);
            } catch (Throwable t) {
                invokeExceptionCaught(t);
            }
        } else {
            fireChannelActive();
        }
    }

    @Override
    protected void doBeginRead() throws Exception {
        // Channel.read() or ChannelHandlerContext.read() was called
        final SelectionKey selectionKey = this.selectionKey;
        if (!selectionKey.isValid()) {
            return;
        }

        readPending = true;

        final int interestOps = selectionKey.interestOps();
        if ((interestOps & readInterestOp) == 0) {
            selectionKey.interestOps(interestOps | readInterestOp);
        }
    }

二、eventLoop

三、accept流程

四、read流程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值