深入理解Netty及核心组件使用—上

目录

Netty的优势

为什么Netty使用NIO而不是AIO?

Netty基本组件

Bootstrap、EventLoop(Group) 、Channel

事件和 ChannelHandler、ChannelPipeline

ChannelFuture

Netty入门程序

服务端代码

客户端代码

运行结果


Netty的优势

1. API 使用简单,开发门槛低。

2. 功能强大,预置了多种编解码功能,支持多种主流协议。

3. 定制能力强,可以通过 ChannelHandler 对通信框架进行灵活地扩展。

4. 性能高,通过与其他业界主流的 NIO 框架对比,Netty 的综合性能最优。

5. 成熟、稳定,Netty 修复了已经发现的所有 JDK NIO BUG,业务开发人员不需要再为 NIO 的 BUG 而烦恼。

6. 社区活跃,版本迭代周期短,发现的 BUG 可以被及时修复,同时更多的新功能会加入。

7. 经历了大规模的商业应用考验,质量得到验证。


为什么Netty使用NIO而不是AIO?

       Netty 不看重 Windows 上的使用,在 Linux 系统上,AIO 的底层实现仍使用 EPOLL,没有很好实现 AIO,因此在性能上没有明显的优势,而且被 JDK 封装了一层不容易深度优化。

        AIO 有个缺点是接收数据需要预先分配缓存,而不是 NIO 那种需要接收时才需要分配缓存,所以对连接数量非常大但流量小的情况,内存浪费很多。而且 Linux 上 AIO 不够成熟,处理回调结果速度跟不上处理需求。


Netty基本组件

Bootstrap、EventLoop(Group)、Channel

        Bootstrap 是 Netty 框架的启动类和主入口类,分为客户端类Bootstrap和服务器类ServerBootstrap两种。

        Channel 是 Java NIO 的一个基本构造。它代表一个到实体(如一个硬件设备、一个文件、一个网络套接字或者一个能够执行一个或者多个不同的 I/O 操作的程序组件)的开放连接,如读操作和写操作,目前,可以把 Channel 看作是传入(入站)或者传出(出站)数据的载体。因此,它可以被打开或者被关闭,连接或者断开连接。

       EventLoop 可以看成一个线程、EventLoopGroup 自然就可以看成线程组。

事件和 ChannelHandler、ChannelPipeline

       Netty 使用不同的事件来通知我们状态的改变或者是操作的状态。这使得我们能够基于已经发生的事件来触发适当的动作。 Netty 事件是按照它们与入站或出站数据流的相关性进行分类的。

入站数据或者相关的状态更改而触发的事件包括:

连接已被激活或者连接失活、数据读取、用户事件、错误事件。

出站事件是未来将会触发的某个动作的操作结果包括:

打开或者关闭到远程节点的连接、将数据写到或者冲刷到套接字。

       每个事件都可以被分发给 ChannelHandler 类中的某个用户实现的方法,既然事件分为入站和出站,用来处理事件的 ChannelHandler 也被分为可以处理入站事件的 Handler 和出站事件的 Handler,当然有些 Handler 既可以处理入站也可以处理出站。

       Netty提供了大量预定义的可以开箱即用的ChannelHandler实现,包括用于各种协议(如 HTTP 和 SSL/TLS)的ChannelHandler。

       基于 Netty 的网络应用程序中根据业务需求会使用 Netty 已经提供的 ChannelHandler 或者自行开发 ChannelHandler,这些 ChannelHandler 都放在 ChannelPipeline 中统一管理,事件就会在 ChannelPipeline 中流动,并被其中一个或者多个 ChannelHandler 处理。


ChannelFuture

        Netty 中所有的 I/O 操作都是异步的,“异步的意思就是不需要主动等待结果的返回,而是通过其他手段比如,状态通知,回调函数等”,那就是说至少我们需要一种获得异步执行结果的手段。

       JDK 预置了 interface java.util.concurrent.Future,Future 提供了一种在操作完成时通知应用程序的方式。这个对象可以看作是一个异步操作的结果的占位符,它将在未来的某个时刻完成,并提供对其结果的访问。但是其所提供的实现,只允许手动检查对应的操作是否已经完成,或者一直阻塞直到它完成。这是非常繁琐的,所以 Netty 提供了它自己的实现 ChannelFuture,用于在执行异步操作的时候使用。

       一般来说,每个 Netty 的出站 I/O 操作都将返回一个 ChannelFuture。


Netty入门程序

服务端代码

public class EchoServer  {private static final Logger LOG = LoggerFactory.getLogger(EchoServer.class);private final int port;public EchoServer(int port) {this.port = port;}public static void main(String[] args) throws InterruptedException {int port = 9999;EchoServer echoServer = new EchoServer(port);LOG.info("服务器即将启动");echoServer.start();LOG.info("服务器关闭");}public void start() throws InterruptedException {/*线程组*/EventLoopGroup group  = new NioEventLoopGroup();try {/*服务端启动必备*/ServerBootstrap b = new ServerBootstrap();b.group(group).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new EchoServerHandler());}});/*异步绑定到服务器,sync()会阻塞到完成*/ChannelFuture f = b.bind().sync();LOG.info("服务器启动完成。");/*阻塞当前线程,直到服务器的ServerChannel被关闭*/f.channel().closeFuture().sync();} finally {group.shutdownGracefully().sync();}}}

ChannelHandler如下:

public class EchoServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf in = (ByteBuf)msg;System.out.println("server accept :" + in.toString(CharsetUtil.UTF_8));ctx.writeAndFlush(in);}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("连接已建立");super.channelActive(ctx);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}

客户端代码

public class EchoClient {private final int port;private final String host;public EchoClient(int port, String host) {this.port = port;this.host = host;}public void start() throws InterruptedException {/*线程组*/EventLoopGroup group  = new NioEventLoopGroup();try {/*客户端启动必备,和服务器的不同点*/Bootstrap b = new Bootstrap();b.group(group).channel(NioSocketChannel.class)/*指定使用NIO的通信模式*//*指定服务器的IP地址和端口,和服务器的不同点*/.remoteAddress(new InetSocketAddress(host,port))/*和服务器的不同点*/.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new EchoClientHandler());}});/*异步连接到服务器,sync()会阻塞到完成,和服务器的不同点*/ChannelFuture f = b.connect().sync();f.channel().closeFuture().sync();/*阻塞当前线程,直到客户端的Channel被关闭*/} finally {group.shutdownGracefully().sync();}}public static void main(String[] args) throws InterruptedException {new EchoClient(9999,"127.0.0.1").start();}
}

ChannelHandler如下:

public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {/*读取到网络数据后进行业务处理,并关闭连接*/@Overrideprotected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {System.out.println("client Accept"+msg.toString(CharsetUtil.UTF_8));//关闭连接///ctx.close();}/*channel活跃后,做业务处理*/@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ctx.writeAndFlush(Unpooled.copiedBuffer("Hello,Netty",CharsetUtil.UTF_8));}
}

运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2775376.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

用HTML5实现灯笼效果

本文介绍了两种实现效果&#xff1a;一种使用画布&#xff08;canvas&#xff09;标签/元素&#xff0c;另一种不用画布&#xff08;canvas&#xff09;标签/元素主要使用CSS实现。 使用画布&#xff08;canvas&#xff09;标签/元素实现&#xff0c;下面&#xff0c;在画布上…

Transformer实战-系列教程13:DETR 算法解读

&#x1f6a9;&#x1f6a9;&#x1f6a9;Transformer实战-系列教程总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 点我下载源码 1、物体检测 说到目标检测你能想到什么 faster-rcnn系列&#xff0c;开山之作&…

基于 Python opencv 的人脸识别的酒店客房入侵系统的检测

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

【深度学习:掌握监督学习】掌握监督学习综合指南

【深度学习&#xff1a;掌握监督学习】掌握监督学习综合指南 监督学习的定义和简要说明监督学习在人工智能中的重要性和相关性概述什么是监督学习&#xff1f;基本概念主要组件&#xff1a;输入要素和目标标签 训练监督式学习模型监督学习算法的类型分类回归每个类别中的流行算…

Rust 格式化输出

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、format! 宏二、fmt::Debug三、fmt::Display四、? 操作符 循环打印 前言 Rust学习系列-本文根据教程学习Rust的格式化输出&#xff0c;包括fmt::Debug&…

3.4-媒资管理之视频处理+xx-job分布式任务

文章目录 媒资管理6 视频处理6.1 需求6.1.1 总体需求6.7.3 FFmpeg 的基本使用6.7.4 视频处理工具类 6.2 分布式任务处理6.2.1 什么是分布式任务调度6.2.2 XXL-JOB介绍6.2.3 搭建XXL-JOB6.2.3.1 调度中心6.2.3.2 执行器6.2.3.3 执行任务 6.2.4 分片广播 6.3 技术方案6.3.1 作业分…

【博云2023】乘龙一跃腾云海,侧目抬手摘星河

癸卯渐远&#xff0c;甲辰渐至&#xff0c;预示着被汗水浇灌的种子&#xff0c;必将顶开冻土&#xff0c;迎接阳光。 每逢春节&#xff0c;当亲友彼此问候&#xff0c;博云人总能自豪地说&#xff0c;我们认真地、努力地奋斗&#xff0c;让我们能自信地踏上新的征程。 我们的…

【Web】Spring rce CVE-2022-22965漏洞复现学习笔记

目录 原理概览 漏洞简述 Tomcat AccessLogValve 和 access_log 例题: 原理概览 spring框架在传参的时候会与对应实体类自动参数绑定&#xff0c;通过“.”还可以访问对应实体类的引用类型变量。使用getClass方法&#xff0c;通过反射机制最终获取tomcat的日志配置成员属性…

生成验证码-超简单

引言 在Web开发中&#xff0c;验证码是一种常见的防止恶意破解、自动化提交的有效手段。在Java项目中&#xff0c;我们可以使用Hutool工具库快速实现验证码功能。Hutool是一个Java工具包&#xff0c;它以简洁易用著称&#xff0c;其中包含了验证码模块&#xff0c;可以让我们轻…

Django中的SQL注入攻击防御策略

Django中的SQL注入攻击防御策略 SQL注入是一种常见的网络安全威胁&#xff0c;可以导致数据库被非法访问和数据泄露。本文将介绍在Django框架中防止SQL注入攻击的关键方法&#xff0c;包括使用参数化查询、使用ORM、进行输入验证和使用安全的编码实践。 SQL注入是一种利用应用程…

幻兽帕鲁服务器部署与参数修改教程(WindowsLinux)

教程合集 【阿里云部署攻略】&#xff1a;【官方指南】阿里云搭建幻兽帕鲁服务器指南汇总 【腾讯云部署教程】&#xff1a;【官方指南】腾讯云搭建幻兽帕鲁服务器指南汇总 选服务器 阿里云新用户专享优惠&#xff1a;帕鲁官方推荐配置4核16G 以及 8核32G&#xff0c;新用户…

计算机网络相关题目及答案(第五章实验)

实验:套接字编程作业5:ICMP ping 源代码如下: # -*- coding: utf-8 -*- """ SAFA_LIYT """ import socket import os import sys import struct import time import select import binasciiICMP_ECHO_REQUEST = 8# 计算checksum def checks…

编码安全风险是什么,如何进行有效的防护

2011年6月28日晚20时左右&#xff0c;新浪微博突然爆发XSS&#xff0c;大批用户中招&#xff0c;被XSS攻击的用户点击恶意链接后并自动关注一位名为HELLOSAMY的用户&#xff0c;之后开始自动转发微博和私信好友来继续传播恶意地址。不少认证用户中招&#xff0c;也导致该XSS被更…

深入理解ES的倒排索引

目录 数据写入过程 词项字典 term dictionary 倒排表 posting list FOR算法 RBM算法 ArrayContainer BitMapContainer 词项索引 term index 在Elasticsearch中&#xff0c;倒排索引的设计无疑是惊为天人的&#xff0c;下面看下倒排索引的结构。 倒排索引分为词项索引【…

网神 SecGate 3600 防火墙 route_ispinfo_import_save 文件上传漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

ubuntu22.04@laptop OpenCV Get Started: 005_rotate_and_translate_image

ubuntu22.04laptop OpenCV Get Started: 005_rotate_and_translate_image 1. 源由2. translate/rotate应用Demo3 translate_image3.1 C应用Demo3.2 Python应用Demo3.3 平移图像过程 4. rotate_image4.1 C应用Demo4.2 Python应用Demo4.3 旋转图像过程 5. 总结6. 参考资料 1. 源由…

MATLAB环境下用于提取冲击信号的几种解卷积方法

卷积混合考虑了信号的时延&#xff0c;每一个单独源信号的时延信号都会和传递路径发生一 次线性瞬时混合&#xff1b;解卷积的过程就是找一个合适的滤波器&#xff0c;进行反卷积运算&#xff0c;得到源信号的近似解。 声音不可避免的会发生衍射、反射等现象&#xff0c;所以&…

数字图像处理实验记录七(彩色图像处理实验)

一、基础知识 经过前面的实验可以得知&#xff0c;彩色图像中的RGB图像就是一个三维矩阵&#xff0c;有3个维度&#xff0c;它们分别存储着R元素&#xff0c;G元素&#xff0c;B元素的灰度信息&#xff0c;最后将它们合起来&#xff0c;便是彩色图像。 这一次实验涉及CMYK和HS…

中小型网络系统总体规划与设计方法

目录 1.基于网络的信息系统基本结构 2.网络需求调研与系统设计原则 3.网络用户调查 4.网络节点地理位置分布情况 5.网络需求详细分析 6.应用概要分析 7.网络工程设计总体目标与设计原则 8.网络结构与拓扑构型设计方法 9.核心层网络结构设计 10.接入核心路由器 11.汇聚…

2.8学习总结

2.8 1.二叉树的前序遍历 2.二叉树的中序遍历 3.二叉树的后序遍历 4.⼆叉树的层序遍历 5.⼆叉树的层序遍历2 6.二叉树的右视图 7.二叉树的层平均值 8.N叉树的层序遍历 9.每个树行中找最大值 10.填充每个节点的下一个右侧节点指针 11.填充每个节点的下一个右侧节点指针2 12.生命之…