当前位置: 首页 > news >正文

Netty服务端和客户端开发实例

一、Netty服务端开发

在开始使用 Netty 开发 TimeServer 之前,先回顾一下使用 NIO 进行服务端开发的步骤。

(1)创建ServerSocketChannel,配置它为非阻塞模式;

(2)绑定监听,配置TCP 参数,例如 backlog 大小;

(3)创建一个独立的I/O线程,用于轮询多路复用器 Selector;

(4)创建 Selector,将之前创建的 ServerSocketChannel 注册到 Selector 上,监听SelectionKey.ACCEPT;

(5)启动I/0线程,在循环体中执行 Selectorselect0)方法,轮询就绪的 Channel;

(6)当轮询到了处于就绪状态的 Channel 时,需要对其进行判断,如果是OP ACCEPT状态,说明是新的客户端接入,则调用 ServerSocketChannel.accept()方法接受新的客户端:(7)设置新接入的客户端链路 SocketChannel 为非阻塞模式,配置其他的一些TCP 参数(8)将SocketChannel注册到 Selector,监听 OP READ 操作位;

(9)如果轮询的Channel为OP READ,则说明 SocketChannel 中有新的就绪的数据包需要读取,则构造ByteBuffer 对象,读取数据包;

(10)如果轮询的Channel为OP WRITE,说明还有数据没有发送完成,需要继续发送。

import io.netty.bootstrap.ServerBootstrap;import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.CompositeByteBuf;
import io.netty.buffer.Unpooled;
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.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;public class nettyServer {Logger logger = LoggerFactory.getLogger(nettyServer.class);@Value("${netty.port}")int port;@PostConstructpublic void bind() {EventLoopGroup bossrGroup = new NioEventLoopGroup();//接收客户端传过来的请求EventLoopGroup wokerGroup = new NioEventLoopGroup();//接收到请求后将后续操作try {ServerBootstrap b = new ServerBootstrap();b.group(bossrGroup, wokerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 1024)//.childOption(ChannelOption.SO_KEEPALIVE, true).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new serverHandlerAdapter());ch.pipeline().addLast(new StringDecoder());ch.pipeline().addLast(new HeartbeatHandler());ch.pipeline().addLast(new IdleStateHandler(10, 1, 1));}});ChannelFuture f = b.bind(port).sync();} catch (Exception e) {}}
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;public class serverHandlerAdapter extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {super.channelActive(ctx);}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {super.channelRead(ctx, msg);}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {super.channelReadComplete(ctx);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {super.exceptionCaught(ctx, cause);}

二、Netty客户端开发

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelHandler;
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;public class nettyClient {clientHandlerAdapter clientHandlerAdapter = new clientHandlerAdapter();public void conect(String ip, int port) {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(group).channel(NioSocketChannel.class).remoteAddress("", port).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(clientHandlerAdapter);}});b.bind(ip, port).sync();} catch (Exception e) {}}public boolean sendFile() {return clientHandlerAdapter.sendFile();}}

我们从 connect 方法讲起,在第 13 行首先创建客户端处理 I/0 读写的 NioEventLoopGroup 线程组,然后继续创建客户端辅助启动类 Bootstrap,随后需要对其进行配置。与服务端不同的是,它的 Channel 需要设置为 NioSocketChannel,然后为其添加 handler,此处为了简单直接创建匿名内部类,实现 initChannel 方法,其作用是当创建 NioSocketChannel成功之后,在初始化它的时候将它的 ChannelHandler 设置到 ChannelPipeline 中,用于处理网络I/O事件。

客户端启动辅助类设置完成之后,调用 connect 方法发起异步连接,然后调用同步方法等待连接成功。

最后,当客户端连接关闭之后,客户端主函数退出,在退出之前,释放 NIO 线程组的资源。

下面我们继续看下TimeClientHandler 的代码如何实现

相关文章:

Netty服务端和客户端开发实例

一、Netty服务端开发在开始使用 Netty 开发 TimeServer 之前&#xff0c;先回顾一下使用 NIO 进行服务端开发的步骤。(1)创建ServerSocketChannel&#xff0c;配置它为非阻塞模式;(2)绑定监听&#xff0c;配置TCP 参数&#xff0c;例如 backlog 大小;(3)创建一个独立的I/O线程&…...

linux基本指令和权限

目录 一.shell命令以及运行原理 二.Linux常用指令 1. ls 指令 2. pwd命令 3.cd指令 4. touch指令 5.mkdir指令&#xff08;重要&#xff09; 6.rmdir指令 && rm 指令&#xff08;重要&#xff09; 7.man指令&#xff08;重要&#xff09; 8.cp指令&#xff08;重要&…...

滚蛋吧,正则表达式!

大家好&#xff0c;我是良许。 不知道大家有没有被正则表达式支配过的恐惧&#xff1f;看着一行火星文一样的表达式&#xff0c;虽然每一个字符都认识&#xff0c;但放在一起直接就让人蒙圈了~ 你是不是也有这样的操作&#xff0c;比如你需要使用「电子邮箱正则表达式」&…...

序列号和反序列化--java--Serializable接口--json序列化普通使用

序列化和反序列化序列化和反序列化作用为什么需要用途Serializable使用serialVersionUID不设置的后果什么时候修改Externalizable序列化的顺序json序列化序列化和反序列化 序列化&#xff1a;把对象转换为字节序列的过程称为对象的序列化。 反序列化:把字节序列恢复为对象的过…...

Java异步任务编排

多线程创建的五种方式&#xff1a; 继承Thread类实现runnable接口。实现Callable接口 FutureTask(可以拿到返回结果&#xff0c;阻塞式等待。)线程池创建。 ExcutorService service Excutors.newFixedThreadPool(10); service.excute(new Runnable01());另外一种创建线程池…...

Hive与HBase的区别及应用场景

当数据量达到一定量级的时候&#xff0c;存储和统计计算查询都会遇到问题&#xff0c;今天了解一下Hive和Hbase的区别和应用场景。 一、定义 Hive是基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张数据库表&#xff0c;并提供简单的sql查询功能&am…...

C++之单例模式

目录 1. 请设计一个类&#xff0c;只能在堆上创建对象 2. 请设计一个类&#xff0c;只能在栈上创建对象 3.请设计一个类&#xff0c;不能被拷贝 C98 C11 4. 请设计一个类&#xff0c;不能被继承 C98 C11 5. 请设计一个类&#xff0c;只能创建一个对象(单例模式) 设计…...

Redis十大类型——Set与Zset常见操作

Redis十大类型——Set与Zset常见操作Set命令操作简列基本操作展示删除移动剪切集合运算Zset基本操作简列添加展示反转按分数取值获取分数值删除分数操作下标操作如果我们对Java有所了解&#xff0c;相信大家很容易就明白Set&#xff0c;在Redis中也一样&#xff0c;Set的value值…...

车载雷达实战之Firmware内存优化

内存&#xff08;Memory&#xff09;是计算机中最重要的部件之一&#xff0c;计算机运时的程序以及数据都依赖它进行存储。内存主要分为随机存储器&#xff08;RAM&#xff09;,只读存储器&#xff08;ROM&#xff09;以及高速缓存&#xff08;Cache&#xff09;。仅仅雷达的原…...

【剑指Offer】JZ14--剪绳子

剪绳子详解1.问题描述2.解题思路3.具体实现1.问题描述 2.解题思路 首先想到的思路&#xff1a;因为是求乘积的最大值&#xff0c;所以如果截取剩下的是1&#xff0c;那还是它本身就没有意义。从此出发&#xff0c;考虑绳子长度是2、3、4、5…通过穷举法来找规律。 值–》拆分–…...

raspberry pi播放音视频

文章目录目的QMediaPlayerGStreamerwhat is GStreamer体系框架优势omxplayerwhat is omxplayercommand Linekey bindings运行过程中错误ALSA目的 实现在树莓派下外接扬声器&#xff0c; 播放某段音频&#xff0c; 进行回音测试。 QMediaPlayer 首先我的安装是5.11版本。 优先…...

【电子学会】2022年12月图形化二级 -- 老鹰捉小鸡

老鹰捉小鸡 小鸡正在农场上玩耍&#xff0c;突然从远处飞来一只老鹰&#xff0c;小鸡要快速回到鸡舍中&#xff0c;躲避老鹰的抓捕。 1. 准备工作 &#xff08;1&#xff09;删除默认白色背景&#xff0c;添加背景Farm&#xff1b; &#xff08;2&#xff09;删除默认角色小…...

C++的双端队列

双端队列介绍1.双端队列知识需知2.大试牛刀1.双端队列知识需知 由于队列是一种先进先出&#xff08;FIFO&#xff09;的数据结构&#xff0c;因此无法直接从队列的底部删除元素。如果希望从队列的底部删除元素&#xff0c;可以考虑使用双端队列&#xff08;deque&#xff09;。…...

【独家】华为OD机试 - 拼接 URL(C 语言解题)

最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 最近更新的博客使用说明本期…...

为什么使用Junit单元测试?Junit的详解

Hi I’m Shendi 为什么使用Junit单元测试&#xff1f;Junit的详解 Junit简介 Junit是一个Java语言的单元测试框架。 单元测试是一个对单一实体&#xff08;类或方法&#xff09;的测试 JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架&#xff08;regression test…...

怎么学好嵌入式Linux系统和驱动

嵌入式专业是一门实践性非常强的学科&#xff0c;只有多动手&#xff0c;多实践&#xff0c;多编程&#xff0c;多调试&#xff0c;多看书&#xff0c;多思考才能真正掌握好嵌入式开发技术。 现在很多同学也意识到了学校培养模式和社会需求脱节问题&#xff0c;有一部分同学也先…...

Spring Aware总结

概述 Spring中Aware到底是什么意思&#xff1f; 我们在看Spring源码的时候&#xff0c;经常可以看到xxxAwarexxx的身影&#xff0c;通常我会很疑惑&#xff0c;Aware到底是什么意思呢&#xff1f; 比如图片中这些包含Aware关键字的类或者接口。 我对下面3个类或接口进行了解…...

【RocketMQ】源码详解:Broker端消息刷盘流程

消息刷盘 同步入口&#xff1a;org.apache.rocketmq.store.CommitLog.GroupCommitService 异步入口&#xff1a;org.apache.rocketmq.store.CommitLog.FlushRealTimeService 刷盘有同步和异步两种&#xff0c;在实例化Commitlog的时候&#xff0c;会根据配置创建不同的服务 p…...

编码器SIQ-02FVS3驱动

一.简介 此编码器可以是功能非常强大&#xff0c;可以检测左右转动&#xff0c;和按键按下&#xff0c;所以说这一个编码器可以抵三个按键&#xff0c;而且体积非常小&#xff0c;使用起来比三个按键要高大尚&#xff0c;而且驱动也简单。唯一不足的点就是价格有点小贵6-8元才…...

【2021.9.7】记一次exe手动添加shellcode

【2021.9.7】记一次exe手动添加shellcode 文章目录【2021.9.7】记一次exe手动添加shellcode0.大致思路1.获取MessageBox的真实地址VA2.通过OD在代码段添加shellcode3.dump出数据,设置程序OEP4.测试dump出来的exe5.方法总结测试的exe和添加了shellcode的exe&#xff1a;链接&…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...