Netty-初体验

news2024/11/17 8:22:15

Netty

  • 引入依赖
  • 服务端
  • 服务端处理读写业务的Handler
  • 客户端
  • 实现客户端handler

在这里插入图片描述

Netty具备设计优雅、使⽤⽅便、性能强劲等优点,

引入依赖

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

服务端

public class NettyServer {
    public static void main(String[] args) {
        // 创建只处理客户端连接请求的线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup(10);
        // 创建只处理客户端读写业务的线程组
        EventLoopGroup workGroup = new NioEventLoopGroup(10);
        try {
            // 创建服务端启动对象
            ServerBootstrap bootstrap = new ServerBootstrap();
            // 配置参数
            bootstrap.group(bossGroup, workGroup) // 配置group
                    // 配置通道类型(服务器的通道实现)
                    .channel(NioServerSocketChannel.class)
                    // 配置用于存放因没有空闲线程导致连接请求被暂存放到队列中的最大长度
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    // 创建通道初始化的对象并配置该对象,向该对象中添加处理器来实现具体的业务
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            // 添加处理器: 处理器里面是真正处理业务的
                            socketChannel.pipeline().addLast(new NettyServerHandler());
                        }
                    });

            System.out.println("netty的服务端启动了");
            // sync同步阻塞的启动服务端
            ChannelFuture channelFuture = bootstrap.bind(9090).sync();
            // 只要服务没关闭,该方法会一直阻塞
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            // 端口所有连接并清理内存
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}

服务端处理读写业务的Handler

/**
 * 自定义的handler, 实现Netty处理器的规范
 */
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    /**
     * 当有客户端发生数据来时,该方法就会被调用
     * @param ctx 当前上下文对象:含有Channel和pipeline的上下文对象
     * @param msg 客户端发送来的数据
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        System.out.println("客户端发送的数据:" + buf.toString(StandardCharsets.UTF_8));
    }

    /**
     * 读完数据后调用的方法,发送数据给客户端
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // 创建携带的ByteByf对象
        ByteBuf buf = Unpooled.copiedBuffer("hello client".getBytes(StandardCharsets.UTF_8));
        // 把数据写入通道中
        ctx.writeAndFlush(buf);
    }

    /**
     * 异常捕获
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 打印异常
        System.out.println(cause.getMessage());
        // 关闭通道
        ctx.close();
    }
}

客户端

/**
 * Netty客户端
 */
public class NettyClient {
    public static void main(String[] args) {
        // 创建一个线程组用于事件循环
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        // 创建客户端启动对象
        Bootstrap bootstrap = new Bootstrap();
        try {
            // 设置相关参数
            bootstrap.group(eventLoopGroup)
                    .channel(NioServerSocketChannel.class)
                    // 创建通道初始化对象并设置handler业务处理器
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            // 添加处理器,处理器是实现具体业务的
                            socketChannel.pipeline().addLast(new NettyClientHandler());
                        }
                    });

            System.out.println("Netty客户端启动了");
            // 同步阻塞:告知客户端连接的服务器的地址,并启动客户端
            ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9999).sync();
            // 阻塞等待完成操作后关闭通道
            channelFuture.channel().close().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            eventLoopGroup.shutdownGracefully();
        }
    }
}

实现客户端handler

/**
 * 客户端Handler
 */
public class NettyClientHandler extends ChannelInboundHandlerAdapter {
    /**
     * 当客户端连接服务器后调用该方法:向服务端写数据
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ByteBuf byteBuf = Unpooled.copiedBuffer("hello server".getBytes(StandardCharsets.UTF_8));
        ctx.writeAndFlush(byteBuf);
    }

    /**
     * 当通道有事件发生时调用的方法:读取服务器返回的数据
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println("来自服务器" + ctx.channel().remoteAddress() + "的消息:" + byteBuf.toString(StandardCharsets.UTF_8));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}

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

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

相关文章

CVE-2024-0918 TEW-800MB RCE漏洞分析

漏洞描述 固件版本为1.0.1.0的TEW-800MB路由器存在命令注入漏洞。如果攻击者获得了web管理权限&#xff0c;他们可以将命令注入到httpd未知函数中的post请求参数DeviceURL中&#xff0c;从而获得shell权限。。 参考链接 TEW-800MB (notion.site)https://warp-desk-89d.notio…

盘点那些世界名校计算机专业采用的教材

清华、北大、MIT、CMU、斯坦福的学霸们在新学期里要学什么&#xff1f;今天我们来盘点一下那些世界名校计算机专业采用的教材。 书单目录 1.《深入理解计算机系统》&#xff08;原书第3版&#xff09;2. 《算法导论》&#xff08;原书第3版&#xff09;3. 《计算机程序的构造和…

【已解决】Zip压缩文件设置了密码怎么办?

Zip是一种常见的压缩格式文件&#xff0c;文件还可以设置密码保护。那设置了密码的Zip文件要如何打开呢&#xff1f;不清楚的小伙伴一起来看看吧。 想要打开带密码的Zip文件&#xff0c;我们需要用到适用于Zip格式的解压缩软件&#xff0c;比如WinRAR或者7-Zip软件都是可以的。…

【数据结构】_队列

目录 1.概念 2.队列的使用 3.队列模拟实现 4.循环队列 5.双端队列 6.栈与队列的互相实现 6.1 用队列实现栈 6.2 用栈实现队列 1.概念 &#xff08;1&#xff09;队列是只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff1b; &am…

PyTorch深度学习实战(37)——CycleGAN详解与实现

PyTorch深度学习实战&#xff08;37&#xff09;——CycleGAN详解与实现 0. 前言1. CycleGAN 基本原理2. CycleGAN 模型分析3. 实现 CycleGAN小结系列链接 0. 前言 CycleGAN 是一种用于图像转换的生成对抗网络(Generative Adversarial Network, GAN)&#xff0c;可以在不需要配…

分布式事务-CAP定理+BASE理论+解决方案(两阶段提交+TCC事务)

事务就是指一个操作单元&#xff0c;操作单元中的所有操作要么同时成功要么同时失败。单体项目中的事务一般都是使用数据库提供的事务机制来完成的&#xff0c;但是分布式事务的事务参与者位于不同的节点上&#xff0c;也就是分布在不同的服务器上。分布式事务的最大问题就是各…

安卓游戏开发之音频技术优劣分析

一、引言 在安卓游戏开发中&#xff0c;音频处理技术扮演着至关重要的角色&#xff0c;它不仅能够增强游戏的沉浸感和玩家体验&#xff0c;还能通过声音效果传达关键的游戏信息。以下将对几种常见的安卓游戏音频处理技术进行优劣分析&#xff0c;并结合应用场景来阐述其特点。 …

Jmeter之内置函数__property和__P的区别

1. __property函数 作用 读取 Jmeter 属性 语法格式 ${__property(key,var,default)} 参数讲解 小栗子 ${__property(key)} 读取 key 属性如果找不到 key 属性&#xff0c;则返回 key&#xff08;属性名&#xff09; ${__property(key,,default)} 读取 key 属性如果找不到 k…

Linux内核中并发与竞争的处理方法之原子操作简介

一. 简介 当我们发现驱动程序中存在并发和竞争的时候一定要处理掉&#xff0c;接下来我们依次来学习一下 Linux 内核提供的几种并发和竞争的处理方法。 本文学习Linux内核提供的一种处理并发与竞争的方法&#xff1a;原子操作。 二. 原子操作简介 原子操作就是指不能再进一步…

【旧文更新】基于STM32L496的低功耗ADXL345加速度读取、TMP75温度检测

【旧文更新】基于STM32L496的低功耗ADXL345加速度读取、TMP75温度检测 文章目录 关于旧文新发加速度和温度检测附录&#xff1a;Cortex-M架构的SysTick系统定时器精准延时和MCU位带操作SysTick系统定时器精准延时延时函数阻塞延时非阻塞延时 位带操作位带代码位带宏定义总线函…

抖音小店怎么做起来?分享几种起店方式,新手商家认真选择!

大家好&#xff0c;我是电商糖果 网上关于抖音小店的起店方式有很多&#xff0c;有人说这种模式利润高&#xff0c;有人说这种模式长久。 东听一句&#xff0c;西听一句&#xff0c;让很多朋友感到比较迷茫。 根本不知道哪种方式更适合自己。 这里糖果就把网上最常见的五种…

线性代数:线性方程组解的结构

目录 齐次/非齐次方程组的解 Ax 0 的解的性质 定理 Ax b 的解的性质 相关证明 例1 例2 例3 齐次/非齐次方程组的解 Ax 0 的解的性质 定理 Ax b 的解的性质 相关证明 例1 例2 例3

2023年12月 Python(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,共50分) 第1题 下面代码的输出结果是?( ) dict1 = {1: 10, 2: 20, 3: 30} dict2 <

C#,大规模图(Large Graph)的均匀成本搜索之迪杰斯特拉(Dijkstra)算法与源代码

1 均匀成本搜索 均匀成本搜索是迪杰斯特拉算法的变体。这里&#xff0c;我们不是将所有顶点插入到一个优先级队列中&#xff0c;而是只插入源&#xff0c;然后在需要时一个接一个地插入。在每一步中&#xff0c;我们检查项目是否已经在优先级队列中(使用访问数组)。如果是&…

Day04 嵌入式---基本定时器

定时器概述 1、软件定时原理 使⽤纯软件的⽅式实现定时功能。 存在的问题&#xff1a;定时不太精准。CPU死等。 1&#xff09;压栈出栈需要花费时间 2&#xff09;ARM流⽔线体系架构的原因 2、定时器定时原理 使用精准的时基&#xff0c;通过硬件方式&#xff0c;实现定…

k-邻近算法(kNN)

目录 k-近邻算法概述 k-近邻算法的一般流程 kNN算法伪代码 k-近邻算法概述 优点&#xff1a;精度高、对异常值不敏感、无数据输入假定 缺点&#xff1a;计算复杂度高、空间复杂度高 适用数据范围&#xff1a;数值型和标称型 k-近邻算法的一般流程 &#xff08;1&#x…

mybatis数据操作语句

//基于注解 Mapper public interface reboudapt {Select("select * from dept")List<dept> huoqudept();//删除语句Delete("delete from dept where id #{id}")void deletesc(Integer id);//增加语句Insert("insert into dept(name, create_t…

Kubernetes服务网络Ingress网络模型分析、安装和高级用法

文章目录 1、Ingres简介2、Ingres网络模型分析3、安装Ingress4、使用4.1、搭建测试环境4.2、域名访问4.3、路径重写&#xff08;高级用法&#xff09;4.4、流量限制&#xff08;高级用法&#xff09; 5、总结 1、Ingres简介 Ingress翻译过来是“入口”的意思&#xff0c;也就是…

如何使用CanaryTokenScanner识别Microsoft Office文档中的Canary令牌和可疑URL

关于CanaryTokenScanner CanaryTokenScanner是一款功能强大的Canary令牌和可疑URL检测工具&#xff0c;该工具基于纯Python开发&#xff0c;可以帮助广大研究人员快速检测Microsoft Office和Zip压缩文件中的Canary令牌和可疑URL。 在网络安全领域中&#xff0c;保持警惕和主动…

小程序端学习

P2 创建Uni-app 分离窗口 一样的Ctrl S P3 细节知识点 创建新的小程序页面