Netty的第一个简单Demo实现
目录
- 说明
- 需求
- Client
- Server
- 写法总结
- 实现
- 运行
说明
Netty 的一个练习,使用 Netty 连通 服务端 和 客户端,进行基本的通信。
需求
Client
- 连接服务端成功后,打印
连接成功 - 给服务端发送消息
HelloServer
Server
- 客户端连接成功后,打印
连接成功 - 读取到客户端的消息后,打印到控制台,并回复消息
HelloClient - 客户端断开后,打印
客户端断开连接
写法总结
- 对于
服务端和客户端的启动代码基本不变,可能会根据需要修改一些配置参数 业务逻辑都写在各种 Handler 里,根据规范,需要继承Netty已有的XxxHandler- 所有的
Handler都需要在socketChannel.pipeline()中以链表的形式逐个执行,细节放到原理分析 ChannelInboundHandlerAdapter中用到的方法

实现

- 导包
<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.35.Final</version></dependency>
- 创建
NettyServer,用于启动服务端
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;public class NettyServer {public static void main(String[] args) throws Exception {// 创建 boss 线程组,处理 连接请求,个数代表有 几主,每个 主 都需要配置一个单独的监听端口NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);// 创建 worker 线程组,处理 具体业务,个数代表有NioEventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap serverBootstrap = new ServerBootstrap();// 创建 Server 启动器,配置必要参数:bossGroup, workerGroup, channel, handlerserverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {// 对workerGroup的SocketChannel设置 个性化业务HandlersocketChannel.pipeline().addLast(new NettyServerHandler());}});System.out.println("Netty Server start ...");ChannelFuture channelFuture = serverBootstrap.bind(9000).sync();// 给 channelFuture 添加监听器,监听是否启动成功/*channelFuture.addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture channelFuture) throws Exception {if (channelFuture.isSuccess()) {System.out.println("启动成功");} else {System.out.println("启动失败");}}});*/channelFuture.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}
- 创建
NettyServerHandler,实现具体业务
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;/*** 自定义Handler需要继承netty规定好的某个HandlerAdapter (规范)* 业务逻辑:* 连接成功后,打印 连接成功* 收到客户端的消息时,打印,并回复消息** @author liuhuan*/
public class NettyServerHandler extends ChannelInboundHandlerAdapter {// 当客户端连接服务器完成就会触发该方法@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("客户端建立连接成功");}@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {System.out.println("客户端断开连接");}// 读取客户端发送的数据@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf byteBuf = (ByteBuf) msg;System.out.println("收到客户端的消息是:" + byteBuf.toString(CharsetUtil.UTF_8));}// 数据读取完毕时触发该方法@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {ByteBuf buf = Unpooled.copiedBuffer("HelloClient".getBytes(CharsetUtil.UTF_8));ctx.writeAndFlush(buf);}// 处理异常, 一般是需要关闭通道@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}
- 创建
NettyClient,启动客户端
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;public class NettyClient {public static void main(String[] args) throws InterruptedException {NioEventLoopGroup group = new NioEventLoopGroup();try {Bootstrap bootstrap = new Bootstrap();// 创建 客户端启动器,配置必要参数bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new NettyClientHandler());}});System.out.println("Netty Client start ...");ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9000).sync();channelFuture.channel().closeFuture().sync();} finally {group.shutdownGracefully();}}
}
- 创建
NettyClientHandler,实现客户端业务逻辑
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;/*** 自定义Handler需要继承netty规定好的某个HandlerAdapter (规范)* 业务逻辑:连接成功后,给服务端发送一条消息** @author liuhuan*/
public class NettyClientHandler extends ChannelInboundHandlerAdapter {// 当客户端连接服务器完成就会触发该方法@Overridepublic void channelActive(ChannelHandlerContext ctx) {System.out.println("连接建立成功");ByteBuf buf = Unpooled.copiedBuffer("HelloServer".getBytes(CharsetUtil.UTF_8));ctx.writeAndFlush(buf);}//当通道有读取事件时会触发,即服务端发送数据给客户端@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {ByteBuf buf = (ByteBuf) msg;System.out.println("收到服务端的消息:" + buf.toString(CharsetUtil.UTF_8));}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();}
}
运行
- 先执行
NettyServer的main方法,启动服务端,查看日志 - 执行
NettyClient的main方法,启动客户端,查看日志 - 关闭
NettyClient服务,查看日志 - 重新执行
NettyClient的main方法,启动客户端,查看日志

相关文章:
Netty的第一个简单Demo实现
目录 说明需求ClientServer写法总结 实现运行 说明 Netty 的一个练习,使用 Netty 连通 服务端 和 客户端,进行基本的通信。 需求 Client 连接服务端成功后,打印连接成功给服务端发送消息HelloServer Server 客户端连接成功后࿰…...
K8S 哲学 - 服务发现 services
apiVersion: v1 kind: Service metadata:name: deploy-servicelabels:app: deploy-service spec: ports: - port: 80targetPort: 80name: deploy-service-podselector: app: deploy-podtype: NodePort service 的 endPoint (ep) 主机端口分配方式 两…...
Springboot工程创建
目录 一、步骤 二、遇到的问题及解决方案 一、步骤 打开idea,点击文件 ->新建 ->新模块 选择Spring Initializr,并设置相关信息。其中组为域名,如果没有公司,可以默认com.example。点击下一步 蓝色方框部分需要去掉,软件包…...
日本站群服务器的优点以及适合该服务器的业务类型?
日本站群服务器的优点以及适合该服务器的业务类型? 日本站群服务器是指位于日本地区的多个网站共享同一台服务器的架构。这种服务器架构有着诸多优点,使其成为许多企业和网站管理员的首选。以下是日本站群服务器的优点以及适合该服务器的业务类型的分析࿱…...
堆的应用2——TOPK问题
TOPK问题 TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。 比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。 情况1——数据量小 对于Top-K问题,能想到的最简单直接的方式就…...
leetcode-5. 最长回文子串
题目描述 给你一个字符串 s,找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。 示例 1: 输入:s "babad" 输出:"bab" 解释:"aba"…...
【Flask 系统教程 1】入门及配置
当你开始学习 Flask 时,了解如何进行基本的配置是非常重要的。Flask 是一个简单而灵活的 Python Web 框架,它允许你快速构建 Web 应用程序,并且易于学习。在这篇博客中,我将介绍如何从零开始进行 Flask 的基础配置,适合…...
石家庄河北银行的
有些时候河北石家庄这边的甲方客户人员就是太苛刻了,尤其是银行业 比如河北银行的信息部的卢斌,兰州人,这个人的人品极度恶劣,对乙方的外包人员特别苛刻,像个大爷一样。自己什么都不会,连sql 都不会写&…...
【CCNP ENCOR OCG】CHAPTER 2》Spanning Tree Protocol
目录 “Do I Know This Already?” Quiz Foundation Topics Spanning Tree Protocol Fundamentals 802.1D Port States Spanning Tree Path Cost Root Bridge Election Locating Root Ports Locating Blocked Designated Switch Ports Verification of VLANs on Trun…...
docker无法映射/挂载根目录
docker无法映射(挂载)根目录下的文件夹只能映射家目录 最近想要使用nas-tools做做刮削,电影存在一个机械磁盘里,机械磁盘被挂载到/data1下,发现一个很奇怪的问题,docker只能挂载成功home目录下的文件夹&am…...
C++中不要重新定义继承而来的non-virtual函数
在 C 中,重定义继承而来的 non-virtual(非虚)函数通常是不推荐的,原因如下: 隐藏父类的实现:如果在派生类中重定义了一个非虚函数,这将隐藏父类中具有相同名称和参数的函数。这意味着即使通过基…...
C++ 对象型参数和返回值
对象型参数和返回值 1.对象型类型作为函数的参数2.对象型参数作为函数的返回值 1.对象型类型作为函数的参数 使用对象类型作为函数的参数或者返回值,可能会产生一些不必要的中间对象 例子: // 使用对象类型作为函数的参数 void test1(Car car) {}完整代…...
LeetCode 字符串专题——KMP算法_28. 找出字符串中第一个匹配项的下标
字符串专题——KMP算法 KMP算法例题 KMP算法 待更新 例题 https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/description/ class Solution {vector<int> next;void getNext(string s){int j-1;next[0]-1;int lens.size();for(int i…...
上班不想用脑子写代码了怎么办?那就试试Baidu Comate啊宝贝
本文目录 前言1、视频编程实战1.1、熟悉代码库中的代码1.2、参考现有代码编写新代码 2、下载使用教程3、使用体验3.1、AutoWork 产品测评3.2、解决有关ajax请求后重定向问题3.3、询问编程相关知识3.3.1、cookie和session的区别与联系3.3.2、数据库中主键外键的相关知识 4、问题…...
【管理咨询宝藏94】某国际咨询公司供应链财务数字化转型方案
本报告首发于公号“管理咨询宝藏”,如需阅读完整版报告内容,请查阅公号“管理咨询宝藏”。 【管理咨询宝藏94】某国际咨询公司供应链&财务数字化转型方案 【格式】PDF版本 【关键词】国际咨询公司、制造型企业转型、数字化转型 【核心观点】 - 172…...
C++_使用邻接表(链表-指针)实现有向图[完整示例及解释]
这个程序是一个图的实现,使用邻接表来表示图的结构: 1. 结构定义部分: - AdjListNode 结构定义了邻接表中的节点,每个节点包含一个名称和一个指向下一个邻接节点的指针。 - Node 结构定义了图中的节点,每个节点…...
Gitlab自动化测试的配置
1. 代码分支命名规范检测 Setting → Repository → Push rules → Branch name,添加分支命名规范对应的正则表达式。如: ^(Release|Tag|Develop|Feature)_._.|Main$ 表示分支名只能以以下关键字之一开头:Release、Tag、Develop和Feature。 …...
Qwen-Audio:推动通用音频理解的统一大规模音频-语言模型(开源)
随着人工智能技术的不断进步,音频语言模型(Audio-Language Models)在人机交互领域变得越来越重要。然而,由于缺乏能够处理多样化音频类型和任务的预训练模型,该领域的进展受到了限制。为了克服这一挑战,研究…...
杭州破冰之举:全面取消住房限购,激发市场新活力
在房地产市场调控的浪潮中,杭州再次走在了前列,于2024年3月14日宣布全面取消二手房限购政策,此举在行业内引发了广泛关注。作为中国经济活力较强的二线城市之一,杭州的这一决策不仅体现了地方政府在房地产市场调控上的灵活应变,也释放出对市场流动性和经济发展的积极信号。…...
ICode国际青少年编程竞赛- Python-1级训练场-变量练习
ICode国际青少年编程竞赛- Python-1级训练场-变量练习 1、 a 8 for i in range(8):Dev.step(a)Dev.turnRight()a - 12、 a 3 for i in range(4):Dev.step(a)Dev.turnRight()a a 1 Dev.step(5)3、 a 4 for i in range(4):Dev.step(2)Dev.step(-5)Dev.step(3)Spaceship.…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
