netty详解

Netty 是一个高性能的网络通信框架,广泛用于构建网络应用程序,如高性能的服务器、客户端和分布式系统。以下是 Netty 的各个组件介绍与原理分析,以及客户端和服务端的实现示例。

一、Netty 的组件介绍

  1. Channel

    • 概念:表示一个连接到网络的对象,负责处理网络 I/O 操作。可以是 TCP、UDP 等。
    • 作用:提供数据读写操作,并可以注册到事件循环。
  2. EventLoop

    • 概念:负责处理 I/O 操作的事件循环。每个 Channel 都会被绑定到一个 EventLoop,通过事件驱动的方式处理 I/O 事件。
    • 作用:提供非阻塞 I/O 操作,使用单线程处理多个 Channel 的事件。
  3. ChannelHandler

    • 概念:用于处理网络 I/O 事件的接口,用户可以实现此接口来自定义业务逻辑。
    • 作用:可以用来处理入站和出站的消息,通过 ChannelPipeline 链接多个处理器。
  4. ChannelPipeline

    • 概念:每个 Channel 维护一个 ChannelPipeline,包含了一系列的 ChannelHandler。
    • 作用:负责将入站和出站的消息传递给不同的处理器,形成一个处理链。
  5. Bootstrap

    • 概念:用于配置和启动 Netty 的客户端或服务端。
    • 作用:简化了 Channel 的创建、配置和启动过程。
  6. Future

    • 概念:表示一个异步计算的结果,提供了一种非阻塞的方式来获取结果。
    • 作用:可以用于处理异步 I/O 操作的完成事件。

二、原理分析

Netty 的设计遵循事件驱动的架构,使用 Reactor 模式处理 I/O 事件。核心流程如下:

  1. 事件循环:通过 EventLoop 处理 I/O 事件,EventLoop 内部有一个 Selector,用于检测事件的发生。

  2. Channel 和 Pipeline:每个 Channel 维护一个 Pipeline,负责处理入站和出站的数据。通过 ChannelHandler 可以实现业务逻辑。

  3. 异步处理:Netty 中的 I/O 操作是异步的,使用 Future 来处理异步结果,确保不会阻塞主线程。

  4. 高性能:通过 NIO 提供的非阻塞 I/O,结合事件驱动的模型,实现高并发的网络通信。

三、实现示例

1. 服务端实现

以下是一个简单的 TCP 服务端示例,使用 Netty 接收并响应客户端消息。

依赖配置(Maven)

<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.68.Final</version>
</dependency>

服务端代码

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.StringDecoder;
import io.netty.handler.codec.StringEncoder;public class NettyServer {private final int port;public NettyServer(int port) {this.port = port;}public void start() throws InterruptedException {EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ch.pipeline().addLast(new LineBasedFrameDecoder(1024));ch.pipeline().addLast(new StringDecoder());ch.pipeline().addLast(new StringEncoder());ch.pipeline().addLast(new SimpleServerHandler());}});ChannelFuture f = b.bind(port).sync();f.channel().closeFuture().sync();} finally {workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}public static void main(String[] args) throws InterruptedException {new NettyServer(8080).start();}
}

处理器代码

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;public class SimpleServerHandler extends SimpleChannelInboundHandler<String> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) {System.out.println("Received: " + msg);ctx.writeAndFlush("Hello from server\n");}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();}
}
2. 客户端实现

以下是一个简单的 TCP 客户端示例,使用 Netty 发送消息到服务端并接收响应。

客户端代码

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.StringDecoder;
import io.netty.handler.codec.StringEncoder;public class NettyClient {private final String host;private final int port;public NettyClient(String host, int port) {this.host = host;this.port = port;}public void start() throws InterruptedException {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ch.pipeline().addLast(new LineBasedFrameDecoder(1024));ch.pipeline().addLast(new StringDecoder());ch.pipeline().addLast(new StringEncoder());ch.pipeline().addLast(new SimpleClientHandler());}});ChannelFuture f = b.connect(host, port).sync();f.channel().writeAndFlush("Hello from client\n");f.channel().closeFuture().sync();} finally {group.shutdownGracefully();}}public static void main(String[] args) throws InterruptedException {new NettyClient("localhost", 8080).start();}
}

处理器代码

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;public class SimpleClientHandler extends SimpleChannelInboundHandler<String> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) {System.out.println("Received from server: " + msg);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();}
}

四、总结

Netty 提供了一种高效且灵活的方式来处理网络通信,适用于构建高性能的服务器和客户端应用程序。通过理解其核心组件和事件驱动的原理,可以有效利用 Netty 的功能来构建各种网络应用。上述示例展示了如何快速实现一个简单的 TCP 服务端和客户端,便于理解 Netty 的基本用法。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ 高级特性——事务

文章目录 前言事务配置事务管理器加上Transactional注解 前言 前面我们学习了 RabbitMQ 的延迟队列&#xff0c;通过延迟队列可以实现生产者生产的消息不是立即被消费者消费。那么这篇文章我们将来学习 RabbitMQ 的事务。 事务 RabbitMQ 是基于 AMQP 协议实现的&#xff0c;…

「C/C++」C/C++标准库之#include <cmath>数学库

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

认识线程 — JavaEE

目录 认识线程&#xff08;Thread&#xff09; 1 线程是什么? 2 为什么要有线程 3 进程和线程的区别 区别一 区别二 区别三 区别四 4. Java的线程和操作系统线程的关系 认识线程&#xff08;Thread&#xff09; 1 线程是什么? 一个线程就是一个 "执行流"。…

Excel-多表数据查找匹配(VLOOKUP)

&#x1f496;简介 Excel的VLOOKUP函数同样可以用来查找表格中的数据。VLOOKUP&#xff08;垂直查找&#xff09;是一个非常有用的函数&#xff0c;它可以在一个表格或数据表的一列中搜索特定的值&#xff0c;并返回与之在同一行上的另一列中的值。 &#x1f4d6;环境 WPS …

R语言机器学习算法实战系列(十二)线性判别分析分类算法 (Linear Discriminant Analysis)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍LDA的原理LDA的步骤教程下载数据加载R包导入数据数据预处理数据描述数据切割构建模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC CurvePRC Curve保存模型总结优点:缺…

【大数据学习 | kafka】producer的参数与结构

1. producer的结构 producer&#xff1a;生产者 它由三个部分组成 interceptor&#xff1a;拦截器&#xff0c;能拦截到数据&#xff0c;处理完毕以后发送给下游&#xff0c;它和过滤器不同并不是丢弃数据&#xff0c;而是将数据处理完毕再次发送出去&#xff0c;这个默认是不…

【c++篇】:探索c++中的std::string类--掌握字符串处理的精髓

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨文章所属专栏&#xff1a;c篇–CSDN博客 文章目录 前言一.std::string对象的创建二.std::string对象的访问三.std::str…

读取有空格的string对象(getline)

文章目录 读取有空格的string对象1.使用标准库中的iostream来写2.**使用getline读取一整行** 读取有空格的string对象 1.使用标准库中的iostream来写 #include<iostream> using namespace std; int main() {string s;cin >> s;cout << s << endl;ret…

探索Python安全字符串处理的奥秘:MarkupSafe库揭秘

文章目录 探索Python安全字符串处理的奥秘&#xff1a;MarkupSafe库揭秘第一部分&#xff1a;背景介绍第二部分&#xff1a;MarkupSafe是什么&#xff1f;第三部分&#xff1a;如何安装MarkupSafe&#xff1f;第四部分&#xff1a;MarkupSafe的简单使用方法1. 使用escape函数2.…

Tomcat安装与使用

Tomcat优点 1、开源免费&#xff1a;是一个免费、开源的Web服务器&#xff0c;可以在任何环境下自由使用&#xff0c;无需支付任何费用。 2、轻量级&#xff1a;是一个轻量级的Web服务器&#xff0c;其核心仅有几百K&#xff0c;启动速度非常快。 3、易于安装和配置&#xff1a…

【笔记】LLM位置编码之标准位置编码

标准位置编码 起源原理证明&#xff1a;对于任何固定的偏移量 k k k&#xff0c; P E p o s k PE_{posk} PEposk​可以表示为 P E p o s PE_{pos} PEpos​的线性函数。计算 P E p o s k 与 P E p o s PE_{posk} 与PE_{pos} PEposk​与PEpos​的内积结论 通俗理解缺点 起源 由…

深度学习之降维和聚类

1 降维和聚类 1.1 图解为什么会产生维数灾难 ​ 假如数据集包含10张照片&#xff0c;照片中包含三角形和圆两种形状。现在来设计一个分类器进行训练&#xff0c;让这个分类器对其他的照片进行正确分类&#xff08;假设三角形和圆的总数是无限大&#xff09;&#xff0c;简单的…

Typora一款极简Markdown文档编辑器和阅读器,实时预览,序列号生成!免费!最新可用!

文章目录 一、Typora下载和安装二、Typora序列号生成 Typora是一款Markdown编辑器和阅读器&#xff0c;风格极简&#xff0c;实时预览&#xff0c;所见即所得&#xff0c;支持MacOS、Windows、Linux操作系统&#xff0c;有图片和文字、代码块、数学公式、图表、目录大纲、文件管…

异常处理与调试:如何编写稳健的代码(8/10)

目录 异常处理与调试&#xff1a;如何编写稳健的代码&#xff08;8/10&#xff09; 介绍 异常概述 常见的异常类型 使用 try...except 处理异常 基本结构 示例&#xff1a;读取文件内容 捕获多个异常 自定义异常 示例&#xff1a;自定义异常类 调试代码 使用 print…

AI跟踪报道第62期-本周AI新闻: 微软推出Copilot的AI Agent和Computer Control

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

重写(外壳不变)

重写&#xff1a;是子类对父类非静态、非private修饰、非final修饰、非构造方法等的实现过程进行重新编写返回值和形参都不能改变。 重写的好处&#xff1a;子类可以根据需要&#xff0c;定义专属于自己的行为。&#xff08;子类能够根据需要实现父类的方法&#xff09; 方法…

封装echarts组件,即插即用(附源码)

前言&#xff1a;最近一个项目刚收工&#xff0c;分享一个常用的封装echarts的组件。 一、直接上组件代码 <template><el-card class"echart-card" shadow"hover"><template v-slot:header><div class"card-header">&…

JS面试八股文(三)

&#x1f60a;文章目录 21.说一下事件循环22.ajax是什么&#xff1f;怎么实现&#xff1f;23.get和post有什么区别&#xff1f;24.Promise的内部原理是什么&#xff1f;它的缺点是什么&#xff1f;25.Promise和async await的区别是什么&#xff1f;26.浏览器的存储方式有哪些&a…

python实战(二)——房屋价格回归建模

一、任务背景 本章将使用一个经典的Kaggle数据集——House Prices - Advanced Regression Techniques进行回归建模的讲解。这是一个房价数据集&#xff0c;与我们熟知的波士顿房价数据集类似&#xff0c;但是特征数量要更多&#xff0c;数据也要更为复杂一些。下面&#xff0c;…

Linux 命令行查看当前目录的总大小/总磁盘空间/磁盘清理

一、du 查看目录空间大小 &#xff08;一&#xff09; du 命令解析 在Linux命令行可以使用 du 命令来查看当前目录的总大小。du 是 disk usage 的缩写&#xff0c;表示磁盘使用情况。 命令解释&#xff1a;总结每个文件的磁盘使用情况&#xff0c;递归地用于目录。 使用格式…