Netty 入门 — 亘古不变的Hello World
这篇文章我们正式开始学习 Netty,在入门之前我们还是需要了解什么是 Netty。
什么是 Netty
为什么很多人都推崇 Java boy 去研究 Netty?Netty 这么高大上,它到底是何方神圣?
用官方的话说:Netty 是一款异步的、基于事件驱动的网络应用程序框架,用以快速开发高性能、高可靠性的网络 IO 程序。
为什么要使用 Netty 呢?因为使用原生的 Java NIO 非常不爽,它存在一系列的问题,比如:
- 使用 Java NIO 需要了解很多概念,而且 API 非常繁琐。
- 使用 Java NIO 编程复杂,一不小心就会 Bug 横飞。
- 开发工作量和难度也很大,例如我们要处理断开重连、网络闪断、半包读写、网络拥塞、异常处理,等等异常情况,处理起来难度比较大。需要非常熟悉 Java 多线程和网络相关知识点,才能编写一个高质量的 Java NIO 程序。
- JDK NIO 的 Bug:例如臭名昭著的 Epoll Bug,它会导致 Selector 空轮询,最终导致 CPU 100%。
使用 Netty,都解决了上面的问题,它具备如下几个优点:
- 容易上手:Netty 是 Java NIO 进行了封装,API 使用简单,开发门槛相对较低。
- 功能强大:预置多种编解码功能,支持多种主流协议,底层 IO 模型随意切换等等。
- 高性能:精心设计的 Reactor 线程模型支持高并发,优秀的内存模型,减少了资源的消耗。
- 设计优雅:灵活且可扩展的事件模型,可以清晰地分离关注点;高度可定制化的线程模型;粘包/粘包、异常检测等机制将我们从繁重的细节中解脱,只需关注业务逻辑。
- 社区活跃:Netty 是目前最为活跃的开源项目之一,版本迭代周期短,bug 修复速度快。
- 安全:完整的 SSL/TLS 和 StartTLS 支持。
- 质量有保障:经过大规模的商业应用考验,质量得到了充分的验证,健壮性无比强大,放心使用吧。
Hello World
接下来我们用 Netty 来实现我们的第一个应用程序:Hello World。该 Hello World 程序大明哥做到尽可能简单,理解不了没有关系,能跑起来就行,毕竟是第一个 demo。
注:大明哥写这篇文章时, Netty 最新版本为:4.1.77,所以后面所有文章 Netty 版本都是基于 4.1.77,包括源码解析。
引入 Netty
<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.77.Final</version>
</dependency>
服务端
服务端的逻辑非常简单,监听 8081 端口,当有客户端连接进来时打印:“**,已连接”,同时打印客户端发送过来的消息。
public class HelloWorldServer {public static void main(String[] args) {// 创建服务端启动引导器ServerBootstrap bootstrap = new ServerBootstrap();// 配置线程模型bootstrap.group(new NioEventLoopGroup());// 指定服务端的 IO 模型bootstrap.channel(NioServerSocketChannel.class);// 定义处理器 Handlerbootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel ch) throws Exception {// 解码ch.pipeline().addLast(new StringDecoder());ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println(ctx.channel() + ",hello world");}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println(new Date() + ":" + msg);}});}});// 绑定 8081 端口bootstrap.bind(8081);}
}
大明哥依次解释上面代码
ServerBootstrap bootstrap = new ServerBootstrap();
:创建服务端启动引导器,ServerBootstrap
将用于引导服务端的启动工作。bootstrap.group(new NioEventLoopGroup());
:给引导器配置一个线程组,也就是 Netty 的线程模型,我们知道 Netty 是基于 Reactor 的线程模型,这里使用的单线程模型,即接受连接和业务处理都是使用同一个线程。bootstrap.channel(NioServerSocketChannel.class);
:指定服务端的 IO 模型,这里我们定义的是 NIO,当然你也可以使用 BIO(OioServerSocketChannel.class),但是一般都不推荐,因为 Netty 的优势就在于 NIO。bootstrap.childHandler()
:这里是定义业务逻辑处理器,简单来说就是客户端向服务端做的操作(连接、读、写),服务端都是在这里进行处理的。bootstrap.bind(8081)
:绑定 8081 端口
一个最简单的 Netty 服务单程序就写完了。
客户端
客户端就做一件事,连接服务端,然后不停地往服务端发送 “hello world”。
public class HelloWorldClient {public static void main(String[] args) throws InterruptedException {// 客户端引导器Bootstrap bootstrap = new Bootstrap();// 配置线程组bootstrap.group(new NioEventLoopGroup());// 指定 IO 类型为 NIObootstrap.channel(NioSocketChannel.class);// 配置 IO 处理器bootstrap.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new StringEncoder());}});// 建立连接Channel channel = bootstrap.connect("127.0.0.1",8081).channel();// 发送消息while (true) {channel.writeAndFlush("hello world..");TimeUnit.SECONDS.sleep(5);}}
}
客户端与服务端的逻辑差不多,只不过它使用的是 Bootstrap,Bootstrap 为客户端启动的引导器,它负责启动客户端和连接服务端。创建引导器后,就和服务端一样了,需要配置线程模型,指定 IO 类型,配置 IO 处理器,最后与服务端建立连接。
bootstrap.connect("127.0.0.1",8081)
:connect()
方法与服务端进行连接,这里需要注意connect()
方法是一个异步方法,它返回的是 ChannelFuture,调用channel()
方法可以获取到对应的 channel(代码里面这种方式处理不是很优雅,我们后续再来讲)。channel.writeAndFlush()
:向服务端发送消息。
到这里一个简单的 Netty 应用就完成了,是不是比使用 NIO 简便很多,也非常清晰。
运行结果
从服务端打印的日志可以看出,当客户端连接服务端后,打印日志:[id: 0xee05e542, L:/127.0.0.1:8081 - R:/127.0.0.1:53354],hello world
,然后每隔 5 秒钟输出 hell world,这和我们开始的预期一样。
可能小伙伴们对上面的代码还不是很理解,对上面的 ServerBootstrap、group()
、channel()
等方法都不明白什么意思,没有关系,因为这篇文章仅仅只是让你对 Netty 有一个简单的认识,后面文章大明哥会将这些概念全部都讲的明明白白的。
【注】:上面两段代码有些瑕疵,但是为了小伙伴更加容易接受,大明哥就尽可能地简单演示,后面会基于它来优化
代码:http://m6z.cn/5zJPpt
相关文章:

Netty 入门 — 亘古不变的Hello World
这篇文章我们正式开始学习 Netty,在入门之前我们还是需要了解什么是 Netty。 什么是 Netty 为什么很多人都推崇 Java boy 去研究 Netty?Netty 这么高大上,它到底是何方神圣? 用官方的话说:Netty 是一款异步的、基于事…...

idea插件开发javax.net.ssl.SSLException: No PSK available. Unable to resume.
idea插件开发,编译出错 javax.net.ssl.SSLException: No PSK available. Unable to resume.at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:129)at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)at java.base/sun.security.ssl.…...
Selenium的WebDriver操作页面的超时或者元素重叠引起的ElementClickInterceptedException
超时 处理由页面加载引起的超时是在使用 Selenium 进行自动化测试中常见的任务。页面加载可能因网络速度慢、页面复杂性或异步操作而导致超时。以下是一些处理页面加载超时的方法: 1.设置隐式等待时间: 使用 implicitly_wait 方法可以设置隐式等待时间…...
oracle数据库的缓存设置
Oracle缓存由两个参数控制SGA_TARGET和PGA_AGGREGATE_TARGET,设置了这两个参数,其他的基本内存部分都由Oracle自动配置为最优值,这也是Oracle推荐的方式。 SGA_TARGET 和PGA_AGGREGATE_TARGET是动态参数,可以在不重启数据库的情况…...

算法通关村第一关-链表青铜挑战笔记
欢迎来到 : 第一关青铜关 java如何创建链表链表怎么增删改查 我们先了解链表 单链表的概念 我们从简单的创建和增删改查开始. 链表的概念 线性表分为顺序表(数组组成)和链表(节点组成) . 链表又分: 单向 双向有哨兵节点 无哨兵节点循环 不循环 链表是一种物理存储单…...

✔ ★【备战实习(面经+项目+算法)】 10.15学习时间表
✔ ★【备战实习(面经项目算法)】 坚持完成每天必做如何找到好工作1. 科学的学习方法(专注!效率!记忆!心流!)2. 每天认真完成必做项,踏实学习技术 认真完成每天必做&…...
pytorch 训练时raise EOFError EOFError
训练到一半时获取验证数据报错 报错代码 imgs next(iter(val_dataloader)) val_dataloader DataLoader(ImageDataset("data/%s" % opt.dataset_name, transforms_transforms_, unalignedTrue, mode"test"),batch_size5,shuffleTrue,num_workers2,)def …...

node.js+NPM包管理器+Webpack打包工具+前端项目搭建
javascript运行环境(无需依赖html文件) BFF,服务于前端的后端 官网下载安装,node -v查看是否安装成功 ①、创建一个01.js文件 //引入http模块 const httprequire(http)//创建服务器 http.createServer(function(request,respo…...
PCL点云处理之基于FPFH特征的全局配准流程具体实现(二百二十一)
PCL点云处理之基于FPFH特征的全局配准流程具体实现(二百二十一) 一、算法介绍二、算法实现1.代码2.效果一、算法介绍 PCL点云库提供的多种工具,可以组合为一套完整的点云配准流程,这里选择FPFH特征,进行具体的配准流程实现,主要内容包括点云读取、点云法线计算、点云特征…...

ai_drive67_基于不确定性的多视图决策融合
论文链接:https://openreview.net/forum?idOOsR8BzCnl5 https://arxiv.org/abs/2102.02051 代码链接:https://github.com/hanmenghan/TMC Zongbo Han, Changqing Zhang, Huazhu Fu, Joey Tianyi Zhou, Trusted Multi-View Classification, Internatio…...

Docker逃逸---procfs文件挂载
一、产生原因 将宿主机/proc目录挂载进了容器,而该目录内的/proc/sys/kernel/core_pattern文件是负责进程奔溃时内存数据转储的,当第一个字符是| 管道符时,后面的部分会以命令行的方式进行解析并运行,攻击者可以将恶意文件写入该…...

[Python小项目] 从桌面壁纸到AI绘画
从桌面壁纸到AI绘画 一、前言 1.1 确认问题 由于生活和工作需要,小编要长时间的使用电脑,小编又懒,一个主题用半年的那种,所以桌面壁纸也是处于常年不更换的状态。即时改变主题也是在微软自带的壁纸中选择,而这些自…...

【Docker 内核详解】namespace 资源隔离(五):User namespaces
【Docker 内核详解 - namespace 资源隔离】系列包含: namespace 资源隔离(一):进行 namespace API 操作的 4 种方式namespace 资源隔离(二):UTS namespace & IPC namespacenamespace 资源隔…...

网络原理必知会
衔接上文:网络原理必知会_念君思宁的博客-CSDN博客 流量控制: 流量控制也是保证可靠性的机制 对于滑动窗口,批量发送数据而言,窗口越大,相当于批量发送的数据越多,整体的速度也就越快了,但是&…...

ELK 日志分析系统介绍与部署
目录 一、ELK 简介: 1.开源工具介绍: 2.其它组件: 2.1 Filebeat: 2.2 Fluentd: 2.3 缓存/消息队列(redis、kafka、RabbitMQ等): 3. filebeat 结合 logstash 带来好处: 二、为什么要…...

Android 内存治理之线程
1、 前言 当我们在应用程序中启动一个线程的时候,也是有可能发生OOM错误的。当我们看到以下log的时候,就说明系统分配线程栈失败了。 java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Out of memory这种情况可能是两种原因导致的。…...
三、K8S之ReplicaSet
ReplicaSet 一、概述 Kubernetes最核心的功能是编排,编排操作都是依靠控制器对象来完成,高级控制器控制着基础的控制器,基础控制器再去控制Pod,Pod里面再包容器。K8S项目里API对象层级大概就是这样。 而ReplicaSet这个控制器是…...

【基础篇】四、本地部署Flink
文章目录 1、本地独立部署会话模式的Flink2、本地独立部署会话模式的Flink集群3、向Flink集群提交作业4、Standalone方式部署单作业模式5、Standalone方式部署应用模式的Flink Flink的常见三种部署方式: 独立部署(Standalone部署)基于K8S部署…...
简述什么是迭代器(Iterator)?
迭代器(Iterator)是一种设计模式,Java 中的迭代器是集合框架中的一个接口,它可以让程序员遍历集合中的元素而无需暴露集合的内部结构。使用迭代器可以遍历任何类型的集合,例如 List、Set 和 Map 等。 通过调用集合类的 iterator() 方法可以获取一个迭代器,并使用 hasNext…...

DarkGate恶意软件通过消息服务传播
导语 近日,一种名为DarkGate的恶意软件通过消息服务平台如Skype和Microsoft Teams进行传播。它冒充PDF文件,利用用户的好奇心诱使其打开,进而下载并执行恶意代码。这种攻击手段使用了Visual Basic for Applications(VBA࿰…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...