Netty框架使用

article/2025/9/21 10:36:52

前言

首先在使用Netty框架的时候需要了解Netty是一个什么东西。

  • Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。也就是说,Netty 是一个基于NIO的客户、服务器端编程框架。
  • 使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发。
  • “快速”和“简单”并不用产生维护性或性能上的问题。Netty 是一个吸收了多种协议的实现经验,这些协议包括FTP,SMTP,HTTP,各种二进制,文本协议,并经过相当精心设计的项目,最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性。

下面就来看看第一个使用Netty搭建的应用

一、开发环境

首先我们需要准备对应的全套的Netty的jar包,这些可以参考Netty的官方网站
Netty的官网是:http://netty.io
当然也可以访问第三方的中文网站 http://ifeve.com/netty5-user-guide/

准备Netty4+
Eclipse或者IDEA
我这里使用的是IDEA

Netty客户端和服务器端描述

一般情况下,在实际使用的时候更多的关注于服务器端的开发,而很少关注客户端的开发,因为对于不同的业务逻辑会有不同的客户端实现,但是对于这些客户端来说服务器端只有一个。服务器会写数据到客户端并且处理多个客户端的并发连接。从理论上来说,限制程序性能的因素只有系统资源和JVM。为了方便理解,这里举了个生活例子,在山谷或高山上大声喊,你会听见回声,回声是山返回的;
在这个例子中,你是客户端,山是服务器。喊的行为就类似于一个Netty客户端将数据发送到服务器,听到回声就类似于服务器将相同的数据返回给你,你离开山谷就断开了连接,但是你可以返回进行重连服务器并且可以发送更多的数据。

逻辑分析

首先Netty是一个网络框架,所以说就要涉及到客户端和服务器端,这样的话就需要分析一下客户端和服务器端各自具有什么样子的作用,根据具体的作用设计对应的代码。

  1. 客户端连接到服务器
  2. 建立连接后,发送或接收数据
  3. 服务器处理所有的客户端连接

这个是建立一个网络应用必须的三个步骤。下面就是具体的按照这三个步骤编写

开始创建应用

首先创建一个服务器端的程序代码如下

服务器端代码
public class ServerHelloWorld {//创建线程组,监听客户端的请求private EventLoopGroup acceptorGroup = null;//处理客户端相关操作线程组,负责处理与客户端端的请求操作。private EventLoopGroup clientGroup = null;//服务器启动相关配置信息private ServerBootstrap bootstrap = null;public ServerHelloWorld() {init();}//初始化private void init() {//初始化线程组acceptorGroup = new NioEventLoopGroup();//处理客户端逻辑clientGroup = new NioEventLoopGroup();//初始化配置信息bootstrap = new ServerBootstrap();//绑定监听线程组bootstrap.group(acceptorGroup, clientGroup);//设置通信模式为NIO模式同步非阻塞bootstrap.channel(NioServerSocketChannel.class);//设定缓存区的大小,单位是字节bootstrap.option(ChannelOption.SO_BACKLOG, 1024);//SO_SNDBUF 表示发送缓冲区,SO_RCVBUF 表示接收缓存区,SO_KEEPALIVE 表示是否开启心跳检查,保证连接有效bootstrap.option(ChannelOption.SO_SNDBUF, 16 * 1024).option(ChannelOption.SO_RCVBUF, 16 * 1024).option(ChannelOption.SO_KEEPALIVE, true);}/*** 监听处理逻辑* @param port 监听端口* @param acceptorHandlers 处理器* @return* @throws InterruptedException*/public ChannelFuture doAccept(int port, final ChannelHandler... acceptorHandlers) throws InterruptedException {/*** childHandler 是服务端的BootStrap独有的方法是用于提供处理对象,提供处理对象可以一次性的增加若干个处理逻辑* 类似责任链模式的处理逻辑,也就是说你增加A 和B两个处理逻辑,在处理逻辑的时候会按照A 和 B 的顺序进行依次处理** ChannelInitializer 用于提供处理器的一个模型对象,这个模型对象,其中定义了一个方法initChannel** initChannel 这个方法适用于初始化处理逻辑责任链条的。可以保证服务端的BootStrap只初始化一次处理器,尽量提供处理器的重用,* 减少了反复创建处理器的操作*/bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(acceptorHandlers);}});/*** bind 方法 用来绑定处理端口,ServerBootstrap可以绑定多个监听端口。多次调用bind方法即可** sync 方法开始启动监听逻辑,返回ChannelFuture 返回结果是监听成功后的未来结果,可以使用* 这个ChannelFuture实现后续的服务器与客户端的交互所以要获取这个ChannelFuture对象*/ChannelFuture future = bootstrap.bind(port).sync();//ChannelFuture future = bootstrap.bind(port).sync();//ChannelFuture future = bootstrap.bind(port).sync();return future;}/*** 回收方法* shutdownGracefully 是一个安全关闭的方法,可以保证不放弃任何一个以接收的客户端请求*/public void release(){this.acceptorGroup.shutdownGracefully();this.clientGroup.shutdownGracefully();}public static void main(String[] args) {ChannelFuture future = null;ServerHelloWorld server = null;try{server = new ServerHelloWorld();//建立连接future = server.doAccept(8081, new ServerHandler());System.out.println("server started.");//关闭连接,回收资源future.channel().closeFuture();} catch (InterruptedException e) {e.printStackTrace();}finally {if (null != future){try {future.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();}}if (null!=server){server.release();}}}
}

对于服务器端的程序来说,创建了两个线程组EventLoopGroup,这里需要通过原理图来详细的说明一下。
在这里插入图片描述
首先对于上面的图来说我们可以看到,在服务器端创建了两个线程组,这个两个线程组一个用来接收请求,一个用来处理业务逻辑,之前提到Netty是使用NIO来设计的,也就是说是同步非阻塞的一种IO。对于NIO、AIO、BIO等来说这些概念在后面的更新中会有总结到,现在就是简单的提供这样的一个概念。
在建立服务器端的时候,会看到一个ServerBootstrap 对象,这个表示服务器端,当然在客户端有一个与这个类对等的类BootStrap类,这两个类为链接的建立提供了很多的配置项信息。

服务端业务处理逻辑
**** @ChannelHandler.Sharable 这个注解表示当前是一个可以分享的处理器,,服务注册此Handler,可以分享给多个客户端使用* 如果不使用这个注解的话,每次客户端请求时,必须为客户端重新创建一个新的处理器Handler对象** bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {*             @Override*             protected void initChannel(SocketChannel ch) throws Exception {*                 ch.pipeline().addLast(new XXXHandler());*             }*         });* 建议自己开发的时候就会使的Handler是可共享的** 如果Handler是一个可分享的,一定避免定义一个可以写的实例变量。不安全**/
@ChannelHandler.Sharable
public class ServerHandler extends ChannelHandlerAdapter {/*** 业务处理逻辑  用于处理读取数据请求的逻辑。它里面的方法和参数如下* @param ctx 上下文对象,其中包含于客户端建立连接的所有资源,比如说对应的Channel* @param msg 读取到的数据,默认类型是bytebuf 这个ByteBuf 是对ByteBuffer的一个封装。简化了操作* @throws Exception*/@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {//强制类型转换ByteBuf readBuffer = (ByteBuf) msg;// 创建一个字节数组,用于保存缓存中的数据。readableBytes 在原生的ByteBuffer也有同样的功能的方法byte[] tempDatas = new byte[readBuffer.readableBytes()];//读取到对应的数据 可以直接读取,这个不需要考虑复位的问题,readBuffer.readBytes(tempDatas);String message = new String(tempDatas,"UTF-8");System.out.println("from client :"+message);if ("exit".equals(message)){//如果客户端断开连接,则关闭上下文ctx.close();return;}String line = "server message to client!";//写操作自动释放缓存,避免内存溢出的问题。ctx.writeAndFlush(Unpooled.copiedBuffer(line.getBytes("UTF-8")));/*** 如果调用的是write方法,不会刷新缓存,缓存中的数据不会发送到客户端,必须调用flush方法进行强制刷出*  ctx.write(msg);*  ctx.flush();*/}/*** 异常处理逻辑* ChannelHandlerContext关闭代表当前与客户端的连接处理逻辑,当客户端异常退出的时候这个异常也会执行* @param ctx* @param cause* @throws Exception*/@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {System.out.println("server exceptionCaught method run …… ");ctx.close();}
}
客户端代码
public class ClientHelloWorld {//处理请求线程组private EventLoopGroup group = null;//服务启动相关配置信息private Bootstrap bootstrap = null;public ClientHelloWorld(){init();}private void init(){group = new NioEventLoopGroup();bootstrap = new Bootstrap();//定义线程组bootstrap.group(group);bootstrap.channel(NioSocketChannel.class);}public ChannelFuture doRequest(String host, int port, final ChannelHandler ... handlers) throws InterruptedException {this.bootstrap.handler(new ChannelInitializer<SocketChannel>() {/*** 客户端的Handler没有childHandler方法,只有Handler方法* 这个方法与服务器的方法是类似的。* 客户端必须绑定处理器,也就说必须调用Handler方法* @param ch* @throws Exception*/@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(handlers);}});//建立连接ChannelFuture future = this.bootstrap.connect(host,port).sync();return future;}public void release(){this.group.shutdownGracefully();}public static void main(String[] args) {ClientHelloWorld client = null;ChannelFuture future = null;try{client = new ClientHelloWorld();future = client.doRequest("localhost",8081,new ClientHandler());Scanner scanner = null;while (true){scanner = new Scanner(System.in);System.out.println("enter message send to server (enter exit close client)");String line = scanner.nextLine();if ("exit".equals(line)){future.channel().writeAndFlush(Unpooled.copiedBuffer(line.getBytes("UTF-8"))).addListener(ChannelFutureListener.CLOSE);break;}future.channel().writeAndFlush(Unpooled.copiedBuffer(line.getBytes("UTF-8")));TimeUnit.SECONDS.sleep(1);}} catch (Exception e) {e.printStackTrace();}finally {if (null!=client){client.release();}if (null!=future){try {future.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();}}}}
}
客户端逻辑处理逻辑
public class ClientHandler extends ChannelHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {try {//强制类型转换ByteBuf readBuffer = (ByteBuf) msg;// 创建一个字节数组,用于保存缓存中的数据。readableBytes 在原生的ByteBuffer也有同样的功能的方法byte[] tempDatas = new byte[readBuffer.readableBytes()];//读取到对应的数据 可以直接读取,这个不需要考虑复位的问题,readBuffer.readBytes(tempDatas);System.out.println("from server " + new String(tempDatas, "UTF-8"));}finally {//用于避免内存溢出ReferenceCountUtil.release(msg);}}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {System.out.println("client exceptionCaught method run …… ");ctx.close();}
}

总结

Netty是一个比较高效的网络应用框架,在很多的项目中都使用到了Netty。弥补了原生的的IO的很多的缺陷,但是也有很多不足的地方,需要更具具体的使用情况进行开发。


http://chatgpt.dhexx.cn/article/8m3lTFnI.shtml

相关文章

Netty框架简介

Netty框架介绍 早已听说Netty牛逼了&#xff0c;最近有时间学习学习&#xff0c;官网地址&#xff1a;https://netty.io/&#xff0c;Java系的多种服务器/大数据框架&#xff0c;都离不开Netty做出的贡献&#xff0c;例如dubbo&#xff0c;elasticsearch等等&#xff0c;采用的…

netty框架android,隻需五步,即可基於Netty框架實現Android內網推送功能。

隻需五步,即可基於Netty框架實現Android內網推送功能。 一、先引入依賴,客戶端和服務端用的都是同一個依賴netty-all。 Android Studio中Gradle配置: compile io.netty:netty-all:5.0.0.Alpha2 IDEA中Maven配置: io.netty netty-all 5.0.0.Alpha2 二、創建消息模塊包。 目前…

Netty框架之Selector轮询器

Selector的原理详解 1.传统多线程网络通信的服务器设计2.线程池版网络通信的服务器设计Selector版网络通信的服务器设计 说到Selector的作用&#xff0c;我们不得不引入 多线程网络通信的设计 1.传统多线程网络通信的服务器设计 服务器每建立一个客户端连接Socket&#xff0c;…

netty框架学习及springboot整合集成

netty框架学习及springboot整合集成 1. Netty基本概念2. Netty框架2.1 Netty框架结构2.1 Netty NIO2.2 Reactor线程模型 3. Springboot集成netty3.1 引入jar包依赖3.2 服务端3.3 客户端 4. 参考资料 从很久以前就接触到netty&#xff0c;也在几个项目中使用netty进行网络通讯对…

Netty框架介绍

Netty框架介绍 一、netty&#xff08;通讯框架&#xff09;介紹 1、什么是netty Netty是一个基于Java NIO类库的异步通讯框架&#xff0c;他的架构特点是&#xff1a;异步非阻塞、基于事件驱动、高性能、高可靠和高定制行。 2、netty应用场景 rpc远程调用框架dubbo底层就是通…

Netty框架简述

Netty是什么&#xff1f; Netty 是一个广泛使用的 Java 网络编程框架&#xff0c;Netty提供异步的、事件驱动的网络应用程序框架和工具&#xff0c;用以快速开发高性能、高可靠性的网络服务器和客户端程序。Netty 的内部实现时很复杂的&#xff0c;但是 Netty 提供了简单易用的…

Netty框架的基本使用

Netty概述 为什么使用Netty 前面了解过的NIO模型&#xff0c;它有可靠性高、吞吐量高的优点&#xff0c;但也存在编程复杂的问题&#xff0c;我们要掌握大量的API&#xff0c;如&#xff1a;各种Channel、Buffer、Selector&#xff0c;还要编程处理特殊情况&#xff0c;如&am…

初识Netty框架

总体概述 Netty作为一款网络通信框架&#xff0c;底层封装了NIO。我们在使用Netty时&#xff0c;无需再关注NIO细节。下图为Netty处理流程图&#xff1a; 应用程序中使用Netty作为网络通信框架后&#xff0c;会形成一条PipeLine链&#xff0c;PipeLine链上有一个一个的事件处…

【java网络编程】netty框架

一、简介 netty是一个高性能、异步事件驱动的NIO框架&#xff0c;它基于Java Nio提供的API实现&#xff0c;提供了对TCP、UDP和文件传输的支持。 二、Reactor模型 Reactor是一种并发处理客户端请求响应的事件驱动模型。服务端在接收到客户端请求后采用多路复用策略&#xff0…

Netty学习二:Netty整体框架

一、Netty的整体结构和源码结构 1. Core层 提供底层网络通信的通用抽象和实现&#xff0c;包括可扩展的事件模型、通用的通信API和支持零拷贝的ByteBuf等。 common模块是Netty的核心基础包&#xff0c;提供丰富的工具类&#xff0c;其他模块都需要依赖该模块。常用的包括&…

Netty框架

概述 Netty 是由 JBOSS 提供的一个 Java 开源框架。Netty 提供异步的、基于事件驱动的网络应用程序框架&#xff0c;用以快速开发高性能、高可靠性的网络 IO 程序。 Netty 是一个基于 NIO 的网络编程框架&#xff0c;使用 Netty 可以帮助你快速、简单的开发出一个网络应用&…

Netty框架基本介绍

NIO 1.概述&#xff1a;NIO全称java non-blocking IO &#xff0c;是指JDK1.4开始&#xff0c;java提供了一系列改进的输入/输出的新特性&#xff0c;被统称为NIO(即New IO )。新增了许多用于处理输入输出的类&#xff0c;这些类都被放在java.nio包及子包下&#xff0c;并且对j…

超详细Netty入门,看这篇就够了!

思维导图 前言 本文主要讲述Netty框架的一些特性以及重要组件&#xff0c;希望看完之后能对Netty框架有一个比较直观的感受&#xff0c;希望能帮助读者快速入门Netty&#xff0c;减少一些弯路。 一、Netty概述 官方的介绍&#xff1a; Netty is an asynchronous event-drive…

SPI通信协议详解(一)

SPI是一个同步的数据总线&#xff0c;也就是说它是用单独的数据线和一个单独的时钟信号来保证发送端和接收端的完美同步。 时钟是一个振荡信号&#xff0c;它告诉接收端在确切的时机对数据线上的信号进行采样。 产生时钟的一侧称为主机&#xff0c;另一侧称为从机。总是只有一个…

SPI协议的介绍

学习内容&#xff1a; 学习SPI协议记录 学习清单&#xff1a; 提示&#xff1a;这里可以添加要学的内容 例如&#xff1a; SPI协议的介绍三根线还是四根线两个概念四种模式SPI时序图SPI优缺点SPI和IIC的对比 学习详细内容&#xff1a; 1.SPI协议的介绍 SPI是串口外设接口…

SPI 通信协议

文章目录 【 1. 概述 】【 2. 原理 】1. 全双工特征下的传输特点2. 二线式、三线式的SPI3. SPI 模式CPOL(Clock Polarity)&#xff0c;时钟极性CPHA (Clock Phase)&#xff0c;时钟相位通信模式_时序 4. 通信过程5. 底层数据传输演示 【 3. SPI底层驱动 】 【 1. 概述 】 SPI …

SPI通信协议基础

文章目录 引言正文串行与并行通信SPI通信简介SPI如何运作&#xff1f;时钟从机选择多个从机MOSI和MISOSPI数据传输步骤 SPI的优缺点优点缺点 好文推荐参考 引言 当您将微控制器连接到传感器&#xff0c;显示器或其他模块时&#xff0c;您是否考虑过这两种设备如何相互通信&…

SPI、I2C、UART(即串口)三种串行总线详解

以下内容均来源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 参考博客 几个串口协议学习整理 UART IIC SPI_mainn的博客-CSDN博客 SPI、I2C、UART三种串行总线的原理、区别及应用_嵌入式Linux,的博客-CSDN博客 RS-232 和 UART 之间有什么区别&#xff1f; - 知乎…

uart、spi、i2c通信协议详解

文章目录 前言一、uart&#xff08;串口&#xff09;介绍使用rs232、rs485拓展 二、I2C介绍1.宏观流程2.时序上3.典型操作 三、spi&#xff08;串行外设接口&#xff09;介绍使用1.宏观上2.微观上 总结1.i2c和spi对比 前言 之前对于各种通信协议学习了就忘&#xff0c;学了就忘…

普通GPIO模拟SPI通信协议(软件SPI)

在工作中偶尔会遇到SPI不够用的情况&#xff0c;而我们又要去使用SPI通信协议&#xff0c;此时就需要我们自己去模拟SPI通信协议。我们知道SPI通信协议有四种模式&#xff0c;它们分别如下所示&#xff1a; 下面是我基于ATSAM4SD16B芯片在Atmel Studio上用普通GPIO模拟的SPI…