iis服务器助手广告
返回顶部
首页 > 资讯 > 精选 >netty服务端辅助类ServerBootstrap如何创建
  • 424
分享到

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

2023-06-29 16:06:34 424人浏览 薄情痞子
摘要

本文小编为大家详细介绍“Netty服务端辅助类ServerBootstrap如何创建”,内容详细,步骤清晰,细节处理妥当,希望这篇“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<Channel>() {                    @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<Channel>() {             @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<AttributeKey<?>, Object> e: childAttrs) {                child.attr((AttributeKey<Object>) 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如何创建”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

--结束END--

本文标题: netty服务端辅助类ServerBootstrap如何创建

本文链接: https://www.lsjlt.com/news/325616.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • netty服务端辅助类ServerBootstrap如何创建
    本文小编为大家详细介绍“netty服务端辅助类ServerBootstrap如何创建”,内容详细,步骤清晰,细节处理妥当,希望这篇“netty服务端辅助类ServerBootstrap如何创建”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢...
    99+
    2023-06-29
  • netty服务端辅助类ServerBootstrap创建逻辑分析
    目录ServerBootstrap创建核心参数初始化流程首先执行绑定注册自身到 EventLoop绑定端口逻辑ServerBootstrap创建 ServerBootstrap 为 ...
    99+
    2024-04-02
  • 如何创建WebSocket服务端
    这篇文章主要介绍“如何创建WebSocket服务端”,在日常操作中,相信很多人在如何创建WebSocket服务端问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何创建WebSocket服务端”的疑惑有所帮助!...
    99+
    2023-06-19
  • 如何创建云服务器端口
    创建云服务器端口需要按照以下步骤: 确定您的云服务器支持哪些端口(例如:Gateway 33、Gateway 4等),因为不同的云服务器供应商支持的端口可能不同。 选择一个端口,并确保这个端口与您的服务器相匹配。您可以在 Web Ser...
    99+
    2023-10-26
    端口 服务器
  • Composer+Git如何创建服务类库
    这篇文章主要讲解了“Composer+Git如何创建服务类库”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Composer+Git如何创建服务类库”吧!Composer 的修改创建服务类库首...
    99+
    2023-06-29
  • 如何获取MySQL服务器端帮助类别列表?
    我们可以通过将关键字内容传递给help命令来获取MySQL服务器端帮助类别的列表。mysql> help contents You asked for help about help category: "Contents&...
    99+
    2023-10-22
  • 如何在Client go中创建服务端口
    在Client go中创建服务端口是一项重要的技能,对于开发人员来说至关重要。通过创建服务端口,可以实现客户端与服务器之间的通信,从而实现数据的传输和交互。本文将由php小编新一为大家...
    99+
    2024-02-08
  • 如何创建云服务器端口命令
    创建云服务器端口命令: 1. 使用netstat-an命令: /tcp:80 /tcp:21 /tcp:20 /tcp:0 使用echo命令: echo server 创建一个名为"echo"的新任务,例如:"echo se...
    99+
    2023-10-27
    端口 命令 服务器
  • 如何创建云服务器端口地址
    创建云服务器端口地址可以通过使用以下步骤: 确定您的云计算平台和操作系统名称:您需要使用云计算平台(如Amazon Web Services)或操作系统(如Microsoft Azure)的名称或版本。 确定您使用的端口号:使用端口号是...
    99+
    2023-10-27
    端口 地址 服务器
  • node.js中ws模块如何创建服务端和客户端
    小编给大家分享一下node.js中ws模块如何创建服务端和客户端,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!首先下载webso...
    99+
    2024-04-02
  • 在阿里云服务器如何创建网页端
    简介 在使用阿里云服务器时,创建一个网页端是非常常见的需求。本文将介绍如何在阿里云服务器上创建一个简单的网页端,并提供一些常用的工具和示例。1. 安装Node.js和npmNode.js是一个流行的JavaScript运行环境,而npm(N...
    99+
    2023-12-31
    阿里 服务器 网页
  • 如何获得“MySQL服务器端帮助”?
    MySQL提供help命令来获取服务器端帮助。该命令的语法如下 -mysql> help search_stringMySQL使用help命令的参数作为搜索字符串来访问MySQL参考手册的内容。如果搜索字符串不匹配,则搜索将失败。例如...
    99+
    2023-10-22
  • 如何创建云服务器端口命令快捷键
    一、PING命令介绍 PING是Python中的一个命令,可以测试服务器是否与目标主机建立连接。它可以通过以下命令来执行: ```python import subprocess def ping(servername, target_h...
    99+
    2023-10-28
    快捷键 端口 命令
  • 如何在阿里云上创建FTP服务器端口?
    FTP服务器端口是一个重要的组成部分,它负责接收和传输文件。本文将详细说明如何在阿里云上创建FTP服务器端口。 FTP服务器端口是在阿里云上创建FTP服务器的重要组成部分,它负责接收和传输文件。如果您想在阿里云上创建FTP服务器,您需要首先...
    99+
    2023-11-06
    阿里 端口 服务器
  • SpringBoot+netty-socketio如何实现服务器端消息推送
    这篇文章主要介绍SpringBoot+netty-socketio如何实现服务器端消息推送,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!首先:因为工作需要,需要对接socket.io框架对接,所以目前只能使用nett...
    99+
    2023-06-14
  • C#如何创建Windows服务
    小编给大家分享一下C#如何创建Windows服务,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!C#创建Windows服务(Windows Services)Win...
    99+
    2023-06-18
  • vps服务器如何创建
    创建VPS服务器的步骤如下:1. 选择合适的VPS提供商:根据自己的需求选择一个可靠的VPS提供商。2. 注册并购买VPS:在选择的...
    99+
    2023-09-14
    vps vps服务器
  • 如何创建云服务器
    创建云服务器需要以下步骤: 确定所需的云服务器类型:选择您需要的云服务器(例如Amazon AWS或Google Cloud Cloud),并根据您的业务需求选择合适的服务提供商。您可以查看不同云服务器的价格和可用性。 选择适当的云服务...
    99+
    2023-10-26
    服务器
  • WMI如何创建系统服务
    这篇文章主要介绍WMI如何创建系统服务,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!代码如下:Const OWN_PROCESS = &H10Const ERR_CONTROL = &H2Const ...
    99+
    2023-06-08
  • linux中如何创建redis服务
    linux中创建redis服务的方法:找下redis的官方的下载地址,如:http://download.redis.io/releases/redis-3.2.8.tar.gz在linux终端,输入命令:“wget http://down...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作