千家信息网

netty服务端辅助类ServerBootstrap如何创建

发表于:2025-11-08 作者:千家信息网编辑
千家信息网最后更新 2025年11月08日,本文小编为大家详细介绍"netty服务端辅助类ServerBootstrap如何创建",内容详细,步骤清晰,细节处理妥当,希望这篇"netty服务端辅助类ServerBootstrap如何创建"文章能
千家信息网最后更新 2025年11月08日netty服务端辅助类ServerBootstrap如何创建

本文小编为大家详细介绍"netty服务端辅助类ServerBootstrap如何创建",内容详细,步骤清晰,细节处理妥当,希望这篇"netty服务端辅助类ServerBootstrap如何创建"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

ServerBootstrap创建

ServerBootstrap 为 netty 建立服务端的辅助类, 以 NIO为例,创建代码如下:

public static void main(String[] args) throws Exception {        ServerBootstrap bs = new ServerBootstrap();        bs.group(new NioEventLoopGroup(1), new NioEventLoopGroup())                .channel(NioServerSocketChannel.class)                .childHandler(new ChannelInitializer() {                    @Override                    protected void initChannel(Channel ch) throws Exception {                        ch.pipeline()                        .addLast(new HttpServerCodec())                        .addLast(new HttpObjectAggregator(65535))                        .addLast(new Controller());                    }                }).bind(8080).sync().channel().closeFuture().sync();    }

核心参数

//配置属性,如 SO_KEEPALIVE 等private final ServerBootstrapConfig config = new ServerBootstrapConfig(this);    //acceot 的 子channel所绑定的 事件循环组"    private volatile EventLoopGroup childGroup;    private volatile ChannelHandler childHandler;

初始化流程

主要为 绑定本地端口 -> 注册自身到 EventLoop , 并注册 accept 和 read 事件 -> EventLoop的主循环中会不断的select注册的channel的事件,并处理。

首先执行绑定

核心逻辑位于

io.netty.bootstrap.AbstractBootstrap.doBind(SocketAddress) 和 io.netty.bootstrap.AbstractBootstrap.initAndRegister()中

private ChannelFuture doBind(final SocketAddress localAddress) {        final ChannelFuture regFuture = initAndRegister();        ..........if (regFuture.isDone()) {            // At this point we know that the registration was complete and successful.            ChannelPromise promise = channel.newPromise();            //绑定逻辑            doBind0(regFuture, channel, localAddress, promise);            return promise;        } else {            // Registration future is almost always fulfilled already, but just in case it's not.            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) {                        // Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an                        // IllegalStateException once we try to access the EventLoop of the Channel.                        promise.setFailure(cause);                    } else {                        // Registration was successful, so set the correct executor to use.                        // See https://github.com/netty/netty/issues/2586                        promise.registered();                        doBind0(regFuture, channel, localAddress, promise);                    }                }            });            return promise;        }    }

注册自身到 EventLoop

先来看 initAndRegister , 核心逻辑就是利用channelFactory初始化一个NioServerSocketChannel实例,并为其设置上config中的参数,然后将其注册到EventLoop中,实际上是委托的channel的Unsafe来实现注册的,核心逻辑位于 AbstractUnsafe.register0 中 完成注册

final ChannelFuture initAndRegister() {        Channel channel = null;        try {            //本例子中实际调用的是  NioServerSocketChannel的构造参数, 并为其设置感兴趣的事件类型为  OP_ACCEPT            channel = channelFactory.newChannel();            init(channel);        } catch (Throwable t) {            if (channel != null) {                // channel can be null if newChannel crashed (eg SocketException("too many open files"))                channel.unsafe().closeForcibly();            }            // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor            return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);        }        ChannelFuture regFuture = config().group().register(channel);        if (regFuture.cause() != null) {            if (channel.isRegistered()) {                channel.close();            } else {                channel.unsafe().closeForcibly();            }        }         return regFuture;    }
 void init(Channel channel) throws Exception {         //设置属性          ..........         p.addLast(new ChannelInitializer() {             @Override             public void initChannel(final Channel ch) throws Exception {                 final ChannelPipeline pipeline = ch.pipeline();                 ChannelHandler handler = config.handler();                 if (handler != null) {                     pipeline.addLast(handler);                 }                 ch.eventLoop().execute(new Runnable() {                     @Override                     public void run() {                         //为NioServerSocketChannel 设置一个 默认的 channelhandler : ServerBootstrapAcceptor , 当发生 accept事件时,将 accept的channel注册到 childEventLoop中                         pipeline.addLast(new ServerBootstrapAcceptor(                                 ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));                     }                 });             }         });     }
private void register0(ChannelPromise promise) {            try {                // check if the channel is still open as it could be closed in the mean time when the register                // call was outside of the eventLoop                if (!promise.setUncancellable() || !ensureOpen(promise)) {                    return;                }                boolean firstRegistration = neverRegistered;                //执行channel到 eventloop的 selector                doRegister();                neverRegistered = false;                registered = true;                // Ensure we call handlerAdded(...) before we actually notify the promise. This is needed as the                // user may already fire events through the pipeline in the ChannelFutureListener.                pipeline.invokeHandlerAddedIfNeeded();                safeSetSuccess(promise);
//触发 InboundChannelHnader.channelRegistered 事件                  pipeline.fireChannelRegistered();
// Only fire a channelActive if the channel has never been registered. This prevents firing // multiple channel actives if the channel is deregistered and re-registered. if (isActive()) { if (firstRegistration) {                        //触发channelActive事件,并会为 channel 绑定上 read 事件                         pipeline.fireChannelActive();                    } else if (config().isAutoRead()) {                        // This channel was registered before and autoRead() is set. This means we need to begin read                        // again so that we process inbound data.                        //                        // See https://github.com/netty/netty/issues/4805                        beginRead();                    }                }            } catch (Throwable t) {                // Close the channel directly to avoid FD leak.                closeForcibly();                closeFuture.setClosed();                safeSetFailure(promise, t);            }        }

绑定端口逻辑

initAndRegister注册成功后,开始执行真正的绑定端口逻辑,核心逻辑位于 NioSocketChannel.doBind0(SocketAddress) 中

private void doBind0(SocketAddress localAddress) throws Exception {        if (PlatformDependent.javaVersion() >= 7) {            SocketUtils.bind(javaChannel(), localAddress);        } else {            SocketUtils.bind(javaChannel().socket(), localAddress);        }    }

至此 绑定个成功, 当触发 ACCEPT 事件时, 会触发 NioServerSocketChannel.doReadMessages -> ServerBootstrapAcceptor.channelRead , 并将 子channel 注册到 childEventLoop中

public void channelRead(ChannelHandlerContext ctx, Object msg) {            final Channel child = (Channel) msg;            child.pipeline().addLast(childHandler);            setChannelOptions(child, childOptions, logger);            for (Entry, Object> e: childAttrs) {                child.attr((AttributeKey) e.getKey()).set(e.getValue());            }            try {                //注册channel                childGroup.register(child).addListener(new ChannelFutureListener() {                    @Override                    public void operationComplete(ChannelFuture future) throws Exception {                        if (!future.isSuccess()) {                            forceClose(child, future.cause());                        }                    }                });            } catch (Throwable t) {                forceClose(child, t);            }        }

读到这里,这篇"netty服务端辅助类ServerBootstrap如何创建"文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注行业资讯频道。

事件 逻辑 核心 服务 辅助 参数 文章 端口 成功 内容 实际 属性 处理 循环 妥当 不断 代码 例子 兴趣 实例 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 端游方舟服务器密码是多少 意识形态及网络安全培训材料 巴楚县福佳网络技术有限公司 姑苏区管理软件开发记录 无线网络安全监管供应商 网络安全管理方法论 描述网络安全工作 分布式数据库部署架构 麒麟信安服务器操作系统v3 淮南电脑服务器回收最新报价 雁塔区网络安全宣传 网络应用服务器管理机配伍图 肇庆支付软件开发设计 自动化专业能做软件开发吗 如何搭建二层ftp服务器 数据库技术专业前景 计算机网络技术兴趣爱好 大数据的应用提高了网络安全性 智慧央厨软件开发多少钱 HP服务器管理口硬件状态 安卓软件开发就业前景怎样 快迅云服务器怎么了 徐汇区网络技术服务值多少钱 电商系统软件开发服务方案多少钱 服务器管理试卷 计算机网络技术遇到问题 派出所采集数据库文件 闪网络技术公开课日记 软件开发前端是干什的 兼职软件开发流程
0