Netty简介及简单客户端/服务端示例代码

什么是Netty?

        Netty是一个NIO客户机-服务器框架,它支持快速而容易地开发网络应用程序,如协议服务器和客户机。它大大简化和简化了网络编程,如TCP和UDP套接字服务器。

        “快速简单”并不意味着生成的应用程序将遭受可维护性或性能问题的困扰。Netty经过了精心的设计,其经验来自于FTP、SMTP、HTTP以及各种基于二进制和文本的遗留协议的实现。因此,Netty成功地找到了一种不妥协地实现易开发性、性能、稳定性和灵活性的方法。

Netty 的应用场景

互联网行业

1)互联网行业: 在分布式系统中, 各个节点之间需要远程服务调用, 高性能的 RPC 框架必不可少, Netty 作为异步高性能的通信框架, 往往作为基础通信组件被这些 RPC 框架使用。

2)典型的应用有: 阿里分布式服务框架 Dubbo 的 RPC 框架使用 Dubbo 协议进行节点间通信, Dubbo 协议默认使用 Netty 作为基础通信组件, 用于实现各进程节点之间的内部通信。

游戏行业

1)无论是手游服务端还是大型的网络游戏, Java 语言得到了越来越广泛的应用。

2)Netty 作为高性能的基础通信组件, 提供了 TCP/UDP 和 HTTP 协议栈, 方便定制和开发私有协议栈, 账号登录服务器。

3)地图服务器之间可以方便的通过 Netty 进行高性能的通信。

大数据领域

1) 经典的 Hadoop 高性能通信和序列化组件 Avro 的 RPC 框架, 默认采用 Netty 进行跨界点通信。

2) 它的 Netty Service 基于 Netty 框架二次封装实现。

代码示例

maven依赖

<dependencies><!--netty依赖--><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.90.Final</version></dependency>
</dependencies>

服务端

Constant类

public class Constant {// 常量,Server需要的一些参数信息,需要根据实际情况进行自定义修改static final int PORT = 8888;   // 可以自定义端口号static final String CLIENT_PREFIX = "Server received:";   // Server显示接收到client发送的信息的前缀static final String SERVER_PREFIX = "Server send:";   // Server将接收到client发送的信息返回给client的前缀
}

NettyServer类

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;/** Netty的Server* 功能:接收client发送的消息并在消息的前缀加上一些内容后返回给客户端* */
public class NettyServer {private final int port;public static void main(String[] args) {int port = Constant.PORT;new NettyServer(port).start();}public NettyServer(int port) {this.port = port;}public void start() {// 创建两个事件循环组EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workerGroup = new NioEventLoopGroup();try {// 创建服务器启动对象ServerBootstrap bootstrap = new ServerBootstrap();// 设置两个处理器,用于接收和返回信息bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) // 使用NioServerSocketChannel作为服务器的通道实现.option(ChannelOption.SO_BACKLOG, 128) // 设置线程队列等待连接的个数.childOption(ChannelOption.SO_KEEPALIVE, true) // 设置保持活动连接状态.childHandler(new ChannelInitializer<SocketChannel>() { // 创建通道初始化对象,设置处理器@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 给处理器添加对应的ChannelHandlerch.pipeline().addLast(new StringDecoder()); // 添加字符串解码器ch.pipeline().addLast(new StringEncoder()); // 添加字符串编码器ch.pipeline().addLast(new ServerHandler()); // 添加服务处理器}});System.out.println("服务端启动,等待客户端连接...");// 绑定端口并启动服务ChannelFuture future = bootstrap.bind(8888).sync();future.channel().closeFuture().sync();} catch (Exception e) {e.printStackTrace();} finally {// 关闭两个事件循环组,释放资源bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}private class ServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {System.out.println(Constant.CLIENT_PREFIX + msg); // 打印收到的客户端信息ctx.writeAndFlush(Constant.SERVER_PREFIX + msg); // 将收到的信息加上前缀返回给客户端}}}

客户端

Constant类

public class Constant {// 常量,Client需要的一些参数信息,需要根据实际情况进行自定义修改static final String HOST = "127.0.0.1";   // 要连接的服务器地址static final int PORT = 8888;   // 要连接的服务器端口号static final String CLIENT_PREFIX = "Client received:";   // Client显示接收到Server发送的信息的前缀
}

NettyClient类

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;import java.util.Scanner;/** Netty的Client* 功能:向server发送控制台输入的消息,并接收server发回的消息并显示* */
public class NettyClient {private final String host;private final int port;private Channel channel;public static void main(String[] args) throws Exception {String host = Constant.HOST;int port = Constant.PORT;new NettyClient(host, port).start();}public NettyClient(String host, int port) {this.host = host;this.port = port;}public void start() throws Exception { // 定义一个名为start的方法,这个方法抛出Exception异常EventLoopGroup group = new NioEventLoopGroup(); // 创建一个NioEventLoopGroup对象,它负责处理I/O操作的多线程事件循环try { // 开始try-catch块,用于捕获可能的异常Bootstrap bootstrap = new Bootstrap(); // 创建一个Bootstrap对象,它是Netty应用程序的入口点bootstrap.group(group) // 设置EventLoopGroup,用于处理I/O操作.channel(NioSocketChannel.class) // 指定用于通信的Channel类型.handler(new ChannelInitializer<SocketChannel>() { // 添加一个ChannelInitializer,用于初始化新连接的Channel@Override // 覆盖ChannelInitializer中的初始化方法protected void initChannel(SocketChannel ch) throws Exception { // 初始化Channelch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8)); // 添加一个StringDecoder,用于将字节流解码为字符串,使用UTF-8编码ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8)); // 添加一个StringEncoder,用于将字符串编码为字节流,使用UTF-8编码ch.pipeline().addLast(new ClientHandler()); // 添加一个ClientHandler,用于处理业务逻辑}});channel = bootstrap.connect(host, port).sync().channel(); // 使用Bootstrap连接服务器,同步连接并获取到ChannelScanner scanner = new Scanner(System.in); // 创建一个Scanner对象,用于从控制台接收用户输入while (true) { // 无限循环,直到用户输入exit命令System.out.print("请输入信息(exit退出):"); // 向控制台输出提示信息String message = scanner.nextLine(); // 从控制台读取用户输入的行,并存储在message变量中channel.writeAndFlush(message + "\n"); // 将用户输入的信息通过Channel发送到服务器,并在信息末尾添加换行符以保证服务器能正确接收信息if (message.equals("exit")) { // 如果用户输入的信息是exit,则退出循环break;}Thread.sleep(1000); // 等待1秒,等待客户端接收并打印服务器发送的消息}scanner.close(); // 关闭Scanner对象,释放资源channel.close(); // 关闭Channel对象,释放资源} finally { // finally块用于无论try块中的代码是否发生异常都会执行的操作group.shutdownGracefully(); // 优雅地关闭EventLoopGroup,释放资源}}private class ClientHandler extends SimpleChannelInboundHandler<String> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {System.out.println(Constant.CLIENT_PREFIX + msg);  // 将服务器的响应打印到控制台}}
}

运行截图:

先启动服务端,再启动客户端,在客户端控制台输入信息后点击回车,可以在服务器端看到服务器接收到客户端发送的信息;可以在客户端看到服务器返回的信息。

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

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

相关文章

【再识C进阶3(上)】详细地认识字符串函数、进行模拟字符串函数以及拓展内容

小编在写这篇博客时&#xff0c;经过了九一八&#xff0c;回想起了祖国曾经的伤疤&#xff0c;勿忘国耻&#xff0c;振兴中华&#xff01;加油&#xff0c;逐梦少年&#xff01; 前言 &#x1f493;作者简介&#xff1a; 加油&#xff0c;旭杏&#xff0c;目前大二&#xff0c;…

基于AVR128单片机智能电风扇控制系统

一、系统方案 模拟的电风扇的工作状态有3种&#xff1a;自然风、常风及睡眠风。使用三个按键S1-S3设置自然风、常风及睡眠风。 再使用两个按键S4和S5&#xff0c;S4用于定时电风扇定时时间长短的设置&#xff0c;每按一次S4键&#xff0c;定时时间增加10秒&#xff0c;最长60秒…

mysql优化之索引

索引官方定义&#xff1a;索引是帮助mysql高效获取数据的数据结构。 索引的目的在于提高查询效率&#xff0c;可以类比字典。 可以简单理解为&#xff1a;排好序的快速查找数据结构 在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&#xff0c;这种数据…

html和css相关操作

html第一个网页 <!DOCTYPE html> <!--html文档声明&#xff0c;声明此文档是一个html5的文档--> <html> <!--html文档开头标签--><head><!--html文档的设置标签&#xff0c;文档的设置及资源的引用都写在这个标签中--><meta charset&q…

如何快速走出网站沙盒期(关于优化百度SEO提升排名)

网站沙盒期是指新建立的网站在百度搜索引擎中无法获得好的排名&#xff0c;甚至被完全忽略的现象。这个现象往往发生在新建立的网站上&#xff0c;因为百度需要时间来评估网站的质量和内容。蘑菇号www.mooogu.cn 为了快速走出网站沙盒期&#xff0c;需要优化百度SEO。以下是5个…

3D成像技术概述

工业4.0时代,三维机器视觉备受关注,目前,三维机器视觉成像方法主要分为光学成像法和非光学成像法,这之中,光学成像法是市场主流。 飞行时间3D成像 飞行时间成像(Time of Flight),简称TOF,是通过给目标连续发送光脉冲,然后用传感器接收从物体返回的光,通过探测光脉…

力扣刷题-链表理论基础

什么是链表 什么是链表&#xff0c;链表是一种通过指针串联在一起的线性结构&#xff0c;每一个节点由两部分组成&#xff0c;一个是数据域一个是指针域&#xff08;存放指向下一个节点的指针&#xff09;&#xff0c;最后一个节点的指针域指向null&#xff08;空指针的意思&a…

毫米波雷达 TI IWR1443 在 ROS 中进行 octomap 建图

个人实验记录 /mmwave_ti_ros/ros_driver/src/ti_mmwave_rospkg/launch/1443_multi_3d_0.launch <launch><!-- Input arguments --><arg name"device" value"1443" doc"TI mmWave sensor device type [1443, 1642]"/><arg…

minio文件上传

1.代码 大佬仓库&#xff1a;https://gitee.com/Gary2016/minio-upload?_fromgitee_search 关于这个代码的讲解&#xff1a;来自b站 2.准备minio 参考&#xff1a;[1]、[2] 2.1 下载 官网&#xff1a;https://min.io/download#/windows 2.2 启动 ①准备一个data文件夹…

Android开发笔记 :理解Fragment

Android开发笔记&#xff1a;理解Fragment 导言 本篇文章产生的原因很简单&#xff0c;就是我在了解Android Jetpack中的Lifecycle框架时发现Lifecycle具体时间和状态的更新都是由一个名为ReportFragment的Fragment来跟踪的&#xff0c;为了更好的了解Fragment是如何追踪Activ…

以太网协议

以太网 以太网协议格式&#x1f3a8;目的地址,源地址mac地址格式 以太网协议格式&#x1f3a8; 目的地址,源地址 此处的地址,叫做mac地址(物理地址),长度是6个字节 mac地址的作用也是用来区分不同的主机 IP地址的长度是4字节 IP地址负责网络层(整体)转发,mac地址负责数据链路层…

pytest框架运行时的参数,以及多线程分布式运行用例、运行指定模块用例

一、运行时的参数 在上一篇博客中写了pytest最为核心的运行时前后置如何设置&#xff0c;细心的朋友可能也会发现其实我们当时就加过运行时的参数-vs。 pytest.main([‘-s’])&#xff1a;能打印出调试信息&#xff0c;print()或者日志都可以直接打印在控制台上。 pytest.ma…

基于微信小程序的房屋租赁系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言运行环境说明用户微信小程序端的主要功能有&#xff1a;户主微信小程序端的主要功能有&#xff1a;管理员的主要功能有&#xff1a;具体实现截图详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考论文…

CSRF攻击(跨站请求伪造)

1.CSRF原理 程序员开发的时候&#xff0c;未对相关页面进行token和referer判断&#xff0c;造成攻击者可构造自己的URL地址欺骗用户进行点击 漏洞分析&#xff08;低级可绕过&#xff09; 通过这个可以更改密码 改为了password 中级多了referer头可以绕过 源代码 多了一个refer…

MVC设计思想理解和ASP.NET MVC理解

三层模式 三层模式包括:UI层,业务逻辑层,数据访问层,模型层 MVC设计思想和ASP.NET MVC理解 MVC设计思想: MVC的思想就是把我们的程序分为三个核心的模块,这三个模块的详细介绍如下: 模型(Model) :负责封装与引用程序的业务逻辑相关的数据以及对数据的处理方法。模型层有对…

Xcode15+iOS17适配以及遇到的问题

今天更新了 Xcode15&#xff0c;遇到了一些问题&#xff0c;做下记录希望大家少走点坑。 1.iOS17 SDK 安装失败 Xcode更新完成后&#xff0c;打开项目一直显示 no fund iOS17 sdk&#xff0c;根据项目不同提示可能有区别&#xff0c;根据提示下载后提示安装失败&#xff0c;…

什么是单点登录?什么又是 OAuth2.0?

对于刚开始接触身份认证的朋友对于单点登录&#xff0c;OAuth2.0&#xff0c;JWT 等等会有诸多疑惑&#xff0c;甚至还会问既然有了 JWT 还拿 单点登录做什么&#xff1f;还拿 OAuth2.0 做什么&#xff1f; 不知做过身份认证的 xdm 看到这里是不是感觉这句话有点迷&#xff1f…

简单好用的Python装饰器详解

装饰器&#xff08;Decorators&#xff09;是Python中一种强大而灵活的功能&#xff0c;用于修改或增强函数或类的行为。装饰器本质上是一个函数&#xff0c;它接受另一个函数或类作为参数&#xff0c;并返回一个新的函数或类。它们通常用于在不修改原始代码的情况下添加额外的…

LaTex打出上大下小的公式

想要在latex中打出如下word公式 首先使用 \atop符号 使用如下语句 d_{H(A,B)} max\{{sup\, inf \atop {a \in A\,b \in B}}\,d(a,b), {sup\, inf\,\atop {b\in B\,a\in\,A}}d(b,a)\}. ![在这里插入图片描述](https://img-blog.csdnimg.cn/0c842594716a4693b1124523d53bfcad…

java框架-Spring-IOC

文章目录 一、组件注册包扫描组件注解0&#xff09;、 ComponentScans1&#xff09;、 RestController2&#xff09;、 Srevice3&#xff09;、 Rerpository4&#xff09;、Component 导入第三方包里的组件1&#xff09;、Configuration1&#xff09;、Bean1&#xff09;、Cond…