[Netty源码] 服务端启动过程 (二)
文章目录
- 1.ServerBootstrap
- 2.服务端启动过程
- 3.具体步骤分析
- 3.1 创建服务端Channel
- 3.2 初始化服务端Channel
- 3.3 注册selector
- 3.4 端口绑定
1.ServerBootstrap
ServerBootstrap引导服务端启动流程:
//主EventLoopGroup
NioEventLoopGroup master = new NioEventLoopGroup();
//从EventLoopGroup
NioEventLoopGroup worker = new NioEventLoopGroup();
//服务端引导类
ServerBootstrap bootstrap = new ServerBootstrap();
//配置主从EventLoopGroup
bootstrap.group(master, worker);
//channel选项配置
bootstrap.option(ChannelOption.SO_KEEPALIVE, true).option(ChannelOption.CONNECT_TIMEOUT_MILLIS,5000);
bootstrap.channel(NioServerSocketChannel.class);
//主EventLoopGroup ChannelHandler配置
bootstrap.handler(new ChannelInboundHandlerAdapter(){@Overridepublic void channelRegistered(ChannelHandlerContext ctx) throws Exception {System.out.println("Master:" + ctx.channel().eventLoop().toString());super.channelRegistered(ctx);}
});
//从EventLoopGroup ChannelHandler配置
bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {System.out.println("Child:" + ch.eventLoop().toString());}
});
//调用bind方法开始监听端口8888
ChannelFuture future = bootstrap.bind(8888).sync();
future.channel().closeFuture().sync();master.shutdownGracefully().sync();
以上代码使用的是Netty框架中经典的主从事件驱动模式
2.服务端启动过程
-
main方法调用ServerBootstrap.bind()方法
-
validate()方法验证必要配置参数
-
调用AbstractBootstrap.initAndRegister()方法
-
调用channelFactory.newChannel()方法创建Channel实例
-
ServerBootstrap.init()初始化Channel实例,配置ChannelOption、attributes;在Channel的pipeline中配置默认的ChannelHandler实例
-
将Channel实例注册到主EventLoopGroup中并返回ChannelFuture
-
注册ChannelFuture回调,在完成后调用channel.bind()方法完成端口监听
3.具体步骤分析
1.创建服务端Channel
2.初始化服务端Channel
3.注册Selector
4.端口绑定
3.1 创建服务端Channel
AbstractBootstrap.bind()
- validate(): 验证必要配置参数
- AbstractBootstrap.doBind()
AbstractBootstrap.initAndRegister()
- 利用反射创建Channel, 得到NioServerSocketChannel
- 初始化channel中的一些参数
AbstractBootstrap.channel() 反射创建Channel
利用反射创建channel, 得到ReflectiveChannelFactory
, 调用channelFactory利用工厂模式, 最后生成NioServerSocketChannel
3.2 初始化服务端Channel
ServerBootstrap.init() 初始化一些基本参数
初始化一些Options和Attrs和group和handler的参数
@Overridevoid init(Channel channel) throws Exception {final Map<ChannelOption<?>, Object> options = options0();synchronized (options) {setChannelOptions(channel, options, logger);}final Map<AttributeKey<?>, Object> attrs = attrs0();synchronized (attrs) {for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {@SuppressWarnings("unchecked")AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();channel.attr(key).set(e.getValue());}}ChannelPipeline p = channel.pipeline();final EventLoopGroup currentChildGroup = childGroup;final ChannelHandler currentChildHandler = childHandler;final Entry<ChannelOption<?>, Object>[] currentChildOptions;final Entry<AttributeKey<?>, Object>[] currentChildAttrs;synchronized (childOptions) {currentChildOptions = childOptions.entrySet().toArray(newOptionArray(0));}synchronized (childAttrs) {currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(0));}p.addLast(new ChannelInitializer<Channel>() {@Overridepublic 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() {@Overridepublic void run() {pipeline.addLast(new ServerBootstrapAcceptor(ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));}});}});}
设置 currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs
在Channel的pipeline中配置默认的ChannelHandler实例
ServerBootstrapAcceptor 添加连接器, ServerBootstrapAcceptor本质是一个handler
3.3 注册selector
bind -> initAndRegister -> AbstractChannel.register -> this.eventLoop = eventLoop, register0 实际注册 -> doRegister(), invokeHandlerAddedIfNeeded(), fireChannelRegistered() 传播事件
AbstractChannel.AbstractUnsafe.register()
register0()
AbstractNioChannel.doRegister()
上面有javaChannel.register(), 利用jdk底层去创建selector
3.4 端口绑定
bind() -> doBind() -> doBind0() -> AbstracChannel,bind() -> DefaultChannelPipeline.bind() -> AbstractChannlHandlerContext.bind() -> AbstractChannlHandlerContext.invokeBind() -> DefaultChannelPipeline.HeadContext.bind() -> NioSocketChannel.doBind0(), pipeline.fireChannelActive();
最后将会调用DefaultChannelPipeline.HeadContext.bind(), 因为DefaultChannelPipeline在初始化时会设置pipeline队列的首尾分别为DefaultChannelPipeline.HeadContext与DefaultChannelPipeline.TailContext
bind()在Pipeline中走的是出站方法,是从管道的后面向前走,最后到达管道头部的ChannelHandler(也就是DefaultChannelPipeline.HeadContext),这一过程会调用同一方向上所有ChannelHandler的bind()事件。
AbstractBootstrap.doBind0(): 添加一个任务至EventLoop中, 最后将会调用DefaultChannelPipeline.HeadContext.bind()方法
AbstractChannlHandlerContext.invokeBind()
DefaultChannelPipeline.HeadContext.bind() -> AbstractChannel.AbstractUnsafe.bind()
@Overridepublic final void bind(final SocketAddress localAddress, final ChannelPromise promise) {assertEventLoop();if (!promise.setUncancellable() || !ensureOpen(promise)) {return;}boolean wasActive = isActive();try {doBind(localAddress);} catch (Throwable t) {safeSetFailure(promise, t);closeIfClosed();return;}if (!wasActive && isActive()) {invokeLater(new Runnable() {@Overridepublic void run() {pipeline.fireChannelActive();}});}safeSetSuccess(promise);}
- NioSocketChannel.doBind() -> NioSocketChannel.doBind0()
- pipeline.fireChannelActive()
通过在pipline中的层层传递, 现在来到了最终执行bind操作的终点, 执行bind方法,
可以通过SocketUtils.bind() 绑定JDK底层的端口
最后如果触发了一个事件的话, 会调用Channel.read()事件(AbstractNioChannel.doBeginRead()), 这个事件对于服务端来说就是一个新的连接接入。
相关文章:

[Netty源码] 服务端启动过程 (二)
文章目录1.ServerBootstrap2.服务端启动过程3.具体步骤分析3.1 创建服务端Channel3.2 初始化服务端Channel3.3 注册selector3.4 端口绑定1.ServerBootstrap ServerBootstrap引导服务端启动流程: //主EventLoopGroup NioEventLoopGroup master new NioEventLoopGroup(); //从E…...
Week 14
代码源每日一题Div2 106. 订单编号 原题链接:订单编号 思路:这题本来没啥思路,直到获得了某位佬的提示才会做( 我们可以用set来维护一些区间,这些区间为 pair 类型,表示没有使用过的编号,每次…...

【微信小程序】-- 使用 Git 管理项目(五十)
💌 所属专栏:【微信小程序开发教程】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! &…...
leetcode每日一题:134. 加油站
系列:贪心算法 语言:java 题目来源:Leetcode134. 加油站 题目 在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i1 个加油站需要消耗汽油 cost[…...

开放式基金实时排行 API 数据接口
开放式基金实时排行 API 数据接口 多维度参数返回,实时数据,类型参数筛选。 1. 产品功能 返回实时开放式基金排行数据可定义查询基金类型参数;多个基金属性值返回多维指标,一次查询毫秒级返回;数据持续更新与维护&am…...

Android开发中synchronized的实现原理
synchronized的三种使用方式 **1.修饰实例方法,**作用于当前实例加锁,进入同步代码前要获得当前实例的锁。 没有问题的写法: public class AccountingSync implements Runnable{//共享资源(临界资源)static int i0;/*** synchronized 修饰实例方法*/p…...
【华为OD机试 2023最新 】 统一限载货物数最小值(C++)
题目描述 火车站附近的货物中转站负责将到站货物运往仓库,小明在中转站负责调度2K辆中转车(K辆干货中转车,K辆湿货中转车)。 货物由不同供货商从各地发来,各地的货物是依次进站,然后小明按照卸货顺序依次装货到中转车,一个供货商的货只能装到一辆车上,不能拆装,但是…...

【生活工作经验 十】ChatGPT模型对话初探
最近探索了下全球大火的ChatGPT,想对此做个初步了解 一篇博客 当今社会,自然语言处理技术得到了迅速的发展,人工智能技术也越来越受到关注。其中,基于深度学习的大型语言模型,如GPT(Generative Pre-train…...

基于Spring Boot房产销售平台的设计与实现【源码+论文】分享
开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.9 摘要 信息技术的发展…...

不同类型的电机的工作原理和控制方法汇总
电机控制是指对电机的启动、调速(加速、减速)、运转方向和停止进行的控制,不同类型的电机有着不同的工作原理和控制方法。 一、无刷电机 无刷电机是由电机主体和电机驱动板组成的一种没有电刷和换向器的机电一体化产品。在无刷电机中…...

计算机网络管理 TCP三次握手的建立过程,Wireshark抓包分析并验证TCP三次握手建立连接的报文
⬜⬜⬜ ---🟧🟨🟩🟦🟪 (*^▽^*)欢迎光临 🟧🟨🟩🟦🟪---⬜⬜⬜ ✏️write in front✏️ 📝个人主页:陈丹宇jmu 🎁欢迎各位→…...

HTTP/2.x:最新的网页加载技术,快速提高您的SEO排名
2.1 http2概念HTTP/2.0(又称HTTP2)是HTTP协议的第二个版本。它是对HTTP/1.x的更新,旨在提高网络性能和安全性。HTTP/2.0是由互联网工程任务组(IETF)标准化的,并于2015年发布。2.2 http2.x与http1.x区别HTTP…...
机器学习----线性回归
第一关:简单线性回归与多元线性回归 1、下面属于多元线性回归的是? A、 求得正方形面积与对角线之间的关系。 B、 建立股票价格与成交量、换手率等因素之间的线性关系。 C、 建立西瓜价格与西瓜大小、西瓜产地、甜度等因素之间的线性关系。 D、 建立西瓜…...

MS2131 USB 3.0 高清音视频采集+HDMI 环出+混音处理芯片 应用网络直播一体机
MS2131 是一款 USB 3.0 高清视频和音频采集处理芯片,内部集成 USB 3.0 Device 控制器、 数据收发模块、音视频处理模块。MS2131 可以通过 USB 3.0 接口将 HDMI 输入的音视频信号传 送到 PC、智能手机、平板电脑上预览或采集。MS2131 支持 HDMI 环出功能,…...

基于堆与AdjustDown的TOP-K问题
TIPSTOP-K问题TOP-K问题:就是说现在比如说有n个数据,然后需要从这n个数据里面找到最大的或最小的前k个。一般来讲思路的话就是:先把这n个数据给他建一个堆,建堆完成之后,然后就去调堆,然后大概只需要调k次&…...

在CentOS上安装Docker引擎
1,先决条件#### 1-1操作系统要求1-2 卸载旧版本 2,安装方法2-1使用存储库安装设置存储库安装 Docker 引擎 本文永久更新地址: 官方地址:https://docs.docker.com/engine/install/centos/ 1,先决条件 #### 1-1操作系统要求 要安装 Docker Engine,您需要…...

【10】核心易中期刊推荐——模式识别与机器学习
🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…...
【数据结构】并查集
目录 一:用途 二:实现 O(1) 三:例题 例题1:集合 例题2:连通图无向 例题3:acwing 240 食物链 一:用途 将两个集合合并询问两个元素是否在一个集合当中 二:实现 O(1) 每…...
软考--网络攻击分类
网络攻击的主要手段包括口令入侵、放置特洛伊木马程序、拒绝服务(DoS)攻击、端口扫描、网络监听、欺骗攻击和电子邮件攻击等。口令入侵是指使用某些合法用户的账号和口令登录到目的主机,然后再实施攻击活动。特洛伊木马(Trojans)程序常被伪装…...

蓝桥杯刷题冲刺 | 倒计时17天
作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.长草2.分考场1.长草 题目 链接: 长草 - 蓝桥云课 (lanqiao.cn) 题目描述 小明有一…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...