Java教程:Netty知识点详解(十)

开课吧开课吧锤锤2021-02-24 10:08

点赞
有用
分享分享

近年来,随着云计算、大数据等热门技术的发展和普及,Java在企业中越来越受到重视,公司对于Java人才需求也是每年都在增长,对于这样热门的行业,很多人都是心动的,那么对于如何学习,怎么提高Java的技术,那就来看看本篇文章吧。

服务端 bind 方法 ServerBootstrap.bind() 源码解析

这里我们从这里进入:

b.bind(port).sync();

直接从 bind()方法跟进去:

// io.netty.bootstrap.AbstractBootstrap#bind(int)

public ChannelFuture bind(int inetPort) {

    return bind(new InetSocketAddress(inetPort));

}

// 继续跟进

public ChannelFuture bind(SocketAddress localAddress) {

    // 验证group与channelFactory是否为null

    validate(); 

    if (localAddress == null) {

        throw new NullPointerException("localAddress");

    }

    // 这里是一处重点逻辑

    return doBind(localAddress);

}

这里显示校验了 Bootstrap 的 group 与 channelFactory 是否绑定成功。然后继续跟进 doBind() 方法:

private ChannelFuture doBind(final SocketAddress localAddress) {

    // 创建、初始化channel,并将其注册到selector,返回一个异步结果

    final ChannelFuture regFuture = initAndRegister();

    // 从异步结果中获取channel

    final Channel channel = regFuture.channel();

    // 若异步操作执行过程中出现了异常,则直接返回异步对象(直接结束)

    if (regFuture.cause() != null) {

        return regFuture;

    }

    // 处理异步操作完成的情况(可能是正常结束,或发生异常,或任务取消,这些情况都属于有结果的情况)

    if (regFuture.isDone()) {

        ChannelPromise promise = channel.newPromise();

        // 绑定指定的端口

        doBind0(regFuture, channel, localAddress, promise);

        return 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) { // 异步操作执行过程中出现了问题

                    promise.setFailure(cause);

                } else {  // 异步操作正常结果

                    promise.registered();

                    // 绑定指定的端口

                    doBind0(regFuture, channel, localAddress, promise);

                }

            }

        });

        return promise;

    }

}

首先再这里,我们先把这个方法整体的逻辑搞清楚,然后再再去研究他的每一步具体的操作,画个图,先理解这个方法做了什么:

Java

可以在图中结合代码,找到整个 dobind() 的大局处理思路,然后呢,到这里我们还有很多重点细节需要继续跟进,也就是图中标记的 Tag 1、Tag 2。为了方便后面跟进去代码之后方便回来,这里以此标记,然后下面在具体分析 Tag 标记的源码:

补充 Tag 0 :

ChannelPromise 与 ChannelFuture 了解。

Tag 1 :

异步创建、初始化channel,并将其注册到selector

final ChannelFuture regFuture = initAndRegister();

Tag 2 :

绑定指定的端口号:

doBind0(regFuture, channel, localAddress, promise);

补充 Tag 0:ChannelPromise 与 ChannelFuture

ChannelPromise 是一个特殊的 ChannelFuture,是一个可修改的 ChannelFuture。内部提供了修改当前 Future 状态的方法。在 ChannelFuture 的基础上实现了设置最终状态的修改方法。

Java

而 ChannelFuture 只可以查询当前异步操作的结果,不可以修改当前异步结果的 Future 。这里需要知道的就是 ChannelPromise 可以修改当前异步结果的状态,并且在修改状态是会触发监听器。在 doBind 方法中主要用于在处理异步执行一直未结束的的操作,将异步结果存在异常的时,将异常赋值给 ChannelPromise 并返回。

以上内容由开课吧老师敖丙提供,更多Java教程尽在开课吧广场Java教程频道。更多免费课程可以关注公众号“码农集散地”

有用
分享