Netty入门——组件(Channel)一

news2025/2/23 7:39:41

目录

    • 一、channel的主要作用
    • 二、EventLoop处理io任务代码示例
      • 2.1、服务端代码示例
      • 2.2、客户端代码示例
      • 2.3、服务端和客户端查看控制台输出结果
    • 三、ChannelFuture连接问题代码示例
      • 3.1、服务端代码示例
      • 3.2、客户端代码示例
      • 3.3、服务端和客户端查看控制台输出结果
      • 3.4、ChannelFuture出现连接问题的原因
    • 四、ChannelFuture连接问题的处理方式一(使用sync方法同步处理结果)
      • 4.1、服务端代码示例
      • 4.2、客户端代码示例
      • 4.3、服务端和客户端查看控制台输出结果
      • 4.4、客户端代码示例标注位置解释
    • 五、ChannelFuture连接问题的处理方式二(使用addListener方法异步处理结果)
      • 5.1、服务端代码示例
      • 5.2、客户端代码示例
      • 5.3、服务端和客户端查看控制台输出结果
      • 5.4、客户端代码示例标注位置解释

一、channel的主要作用

channel 中的方法作用
close()用来关闭 channel
closeFuture()处理 channel 的关闭,sync 方法作用是同步等待 channel 关闭,addListener 方法是异步等待 channel 关闭
pipeline()添加处理器
write()将数据写入
writeAndFlush()将数据写入并刷出

二、EventLoop处理io任务代码示例

2.1、服务端代码示例

  • 引入pom依赖

     <dependency>
         <groupId>io.netty</groupId>
         <artifactId>netty-all</artifactId>
         <version>4.1.39.Final</version>
     </dependency>
    
  • 服务端

    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.buffer.ByteBuf;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.ChannelInboundHandlerAdapter;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.DefaultEventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    import io.netty.channel.socket.nio.NioSocketChannel;
    import lombok.extern.slf4j.Slf4j;
    
    import java.nio.charset.Charset;
    
    /**
     * @description: EventLoop处理io任务 服务端
     * @author: xz
     */
    @Slf4j
    public class EventLoopServer {
        public static void main(String[] args) {
            //创建一个独立的EventLoopGroup
            DefaultEventLoopGroup normalWorkers = new DefaultEventLoopGroup(2);
            //1、服务端启动器:负责组装netty组件
            new ServerBootstrap()
                    //2、将EventLoop分为boss和worker(即将EventLoop分工细化)
                    // boss即第1个参数,只负责accept事件; worker即第2个参数,只负责socketChannel上的读写
                    .group(new NioEventLoopGroup(1), new NioEventLoopGroup(2))
                    //3、选择服务器的 ServerSocketChannel 实现
                    .channel(NioServerSocketChannel.class)
                    //4、添加服务端处理器
                    .childHandler(
                        // 5. channel 代表和客户端进行数据读写的通道 Initializer 初始化,负责添加别的 handler
                        new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel ch) throws Exception {
                            //6、添加具体 handler
                            ch.pipeline().addLast(normalWorkers,"handler1", new ChannelInboundHandlerAdapter() {
                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    //msg转ByteBuf
                                    ByteBuf buf = (ByteBuf) msg;
                                    //ByteBuf转字符串
                                    log.debug(buf.toString(Charset.defaultCharset()));
                                    //让消息传递给下一个handler
                                    ctx.fireChannelRead(msg);
                                }
                            });
                        }
                    })
                    //7、绑定监听端口
                    .bind(8080);
        }
    }
    

2.2、客户端代码示例

  • 客户端

    import io.netty.bootstrap.Bootstrap;
    import io.netty.buffer.ByteBufAllocator;
    import io.netty.channel.Channel;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.nio.NioSocketChannel;
    import io.netty.handler.codec.string.StringEncoder;
    import lombok.extern.slf4j.Slf4j;
    import java.net.InetSocketAddress;
    /**
     * @description: EventLoop处理io任务 客户端
     * @author: xz
     */
    @Slf4j
    public class EventLoopClient {
        public static void main(String[] args) throws InterruptedException {
            // 1. 客户端启动器
            Channel channel = new Bootstrap()
                    // 2. 添加 EventLoop(事件循环)
                    .group(new NioEventLoopGroup(1))
                    // 3. 选择客户端的 SocketChannel 实现
                    .channel(NioSocketChannel.class)
                    // 4. 添加客户端处理器
                    .handler(new ChannelInitializer<NioSocketChannel>() {
                        // 在连接建立后被调用
                        @Override
                        protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                            //9. 消息会经过通道 handler 处理,这里是将 String => ByteBuf 发出
                            nioSocketChannel.pipeline().addLast(new StringEncoder());
                        }
                    })
                    //5. 连接到服务器
                    .connect(new InetSocketAddress("localhost", 8080))
                    //6. 等待 connect 建立连接完毕
                    .sync()
                    //7. 连接对象
                    .channel();
            System.out.println("打印channel对象==="+channel);
            //8. 发送数据
            channel.writeAndFlush(ByteBufAllocator.DEFAULT.buffer().writeBytes("aaaaaa".getBytes()));
        }
    }
    

2.3、服务端和客户端查看控制台输出结果

  • 先启动服务端,再启动客户端,查看客户端控制台输出,结果如下:
    在这里插入图片描述
  • 再查看服务端控制台输出,结果如下:
    在这里插入图片描述

三、ChannelFuture连接问题代码示例

3.1、服务端代码示例

  • 同步2.1步骤中的代码

3.2、客户端代码示例

  • 将2.2步骤中客户端代码拆开,代码如下

    import io.netty.bootstrap.Bootstrap;
    import io.netty.channel.Channel;
    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.nio.NioSocketChannel;
    import io.netty.handler.codec.string.StringEncoder;
    import io.netty.handler.logging.LogLevel;
    import io.netty.handler.logging.LoggingHandler;
    import lombok.extern.slf4j.Slf4j;
    
    import java.net.InetSocketAddress;
    
    /**
     * @description: EventLoop处理io任务中ChannelFuture连接问题
     * @author: xz
     */
    @Slf4j
    public class ChannelFutureClient {
        public static void main(String[] args) throws InterruptedException {
            client1();
        }
         /**
         * 将客户端代码拆开
         * ChannelFuture连接问题 : connect 方法是异步的,意味着不等连接建立,方法执行就返回了。因此 channelFuture 对象中不能【立刻】获得到正确的 Channel 对象
         * */
        public static void client1() throws InterruptedException {
            ChannelFuture channelFuture = new Bootstrap()
                    .group(new NioEventLoopGroup(1))
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                            nioSocketChannel.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
                            nioSocketChannel.pipeline().addLast(new StringEncoder());
                        }
                    })
                    //1、连接到服务器
                    //异步非阻塞,main方法发起了调用,真正执行connect是nio线程
                    //返回的是 ChannelFuture 对象,它的作用是利用 channel() 方法来获取 Channel 对象
                    .connect(new InetSocketAddress("localhost", 8080));
            //无阻塞向下执行获取channel
            Channel channel = channelFuture.channel();
            log.info("连接未建立,channel对象====={}",channel);
            channel.writeAndFlush("aaaaaaaaaaaaaaaaaa");
        }
     }
    

3.3、服务端和客户端查看控制台输出结果

  • 先启动服务端,再启动客户端,查看客户端控制台输出,结果如下:
    在这里插入图片描述

  • 再查看服务端控制台输出,结果如下:

    在这里插入图片描述

3.4、ChannelFuture出现连接问题的原因

  • 由上述代码示例可知,connect 方法是异步的,意味着不等连接建立,方法执行就返回了。因此 channelFuture 对象中不能【立刻】获得到正确的 Channel 对象。

四、ChannelFuture连接问题的处理方式一(使用sync方法同步处理结果)

4.1、服务端代码示例

  • 同步2.1步骤中的代码

4.2、客户端代码示例

  • 将3.2步骤中客户端代码进行修改,代码如下

    import io.netty.bootstrap.Bootstrap;
    import io.netty.channel.Channel;
    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.nio.NioSocketChannel;
    import io.netty.handler.codec.string.StringEncoder;
    import io.netty.handler.logging.LogLevel;
    import io.netty.handler.logging.LoggingHandler;
    import lombok.extern.slf4j.Slf4j;
    
    import java.net.InetSocketAddress;
    
    /**
     * @description: EventLoop处理io任务中ChannelFuture连接问题及处理结果
     * @author: xz
     */
    @Slf4j
    public class ChannelFutureClient {
        public static void main(String[] args) throws InterruptedException {
            client2();
        }
        public static void client2() throws InterruptedException {
            ChannelFuture channelFuture = new Bootstrap()
                    .group(new NioEventLoopGroup(1))
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                            nioSocketChannel.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
                            nioSocketChannel.pipeline().addLast(new StringEncoder());
                        }
                    })
                    //1、连接到服务器
                    //异步非阻塞,main方法发起了调用,真正执行connect是nio线程
                    .connect(new InetSocketAddress("localhost", 8080));
            //无阻塞向下执行获取channel
            Channel channel = channelFuture.channel();
            log.info("连接未建立,打印channel对象====={}",channel);//2
            //使用sync方法同步处理结果,阻塞当前线程,直到nio线程连接建立完毕
            channelFuture.sync(); // 3
            log.info("建立连接后,打印channel对象====={}",channel); // 4
            channel.writeAndFlush("bbbbbbbbb");
        }
    }
    

4.3、服务端和客户端查看控制台输出结果

  • 先启动服务端,再启动客户端,查看客户端控制台输出,结果如下:
    在这里插入图片描述

  • 再查看服务端控制台输出,结果如下:
    在这里插入图片描述

4.4、客户端代码示例标注位置解释

  • 执行到 2 位置时,连接未建立,打印[id: 0x4de78375]
  • 执行到 3 位置时,sync 方法是同步等待连接建立完成
  • 执行到 4 位置时,连接肯定建立了,打印[id: 0x4de78375, L:/127.0.0.1:53147 - R:localhost/127.0.0.1:8080]

五、ChannelFuture连接问题的处理方式二(使用addListener方法异步处理结果)

5.1、服务端代码示例

  • 同步2.1步骤中的代码

5.2、客户端代码示例

  • 将3.2步骤中客户端代码进行修改,代码如下

    import io.netty.bootstrap.Bootstrap;
    import io.netty.channel.Channel;
    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.nio.NioSocketChannel;
    import io.netty.handler.codec.string.StringEncoder;
    import io.netty.handler.logging.LogLevel;
    import io.netty.handler.logging.LoggingHandler;
    import lombok.extern.slf4j.Slf4j;
    
    import java.net.InetSocketAddress;
    
    /**
     * @description: EventLoop处理io任务中ChannelFuture连接问题及处理结果
     * @author: xz
     */
    @Slf4j
    public class ChannelFutureClient {
        public static void main(String[] args) throws InterruptedException {
            client3();
        }
        public static void client3() throws InterruptedException {
            ChannelFuture channelFuture = new Bootstrap()
                    .group(new NioEventLoopGroup(1))
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                            nioSocketChannel.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
                            nioSocketChannel.pipeline().addLast(new StringEncoder());
                        }
                    })
                    //1、连接到服务器
                    //异步非阻塞,main方法发起了调用,真正执行connect是nio线程
                    .connect(new InetSocketAddress("localhost", 8080));
            //无阻塞向下执行获取channel
            Channel channel = channelFuture.channel();
            log.info("连接未建立,打印channel对象====={}",channel);  // 2
            channelFuture.addListener((ChannelFutureListener) future-> {
                log.info("建立连接后,打印channel对象====={}",future.channel());//3
                channel.writeAndFlush("ccccccccccc");
            });
        }
    }
    

5.3、服务端和客户端查看控制台输出结果

  • 先启动服务端,再启动客户端,查看客户端控制台输出,结果如下:
    在这里插入图片描述

  • 再查看服务端控制台输出,结果如下:
    在这里插入图片描述

5.4、客户端代码示例标注位置解释

  • 执行到 2 位置时,连接未建立,打印[id: 0x01485347]
  • ChannelFutureListener 会在连接建立时被调用(其中 operationComplete 方法),因此执行到 3 位置时,连接肯定建立了,打印[id: 0x01485347, L:/127.0.0.1:53380 - R:localhost/127.0.0.1:8080]

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

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

相关文章

MyBatis的二级缓存

MyBatis的二级缓存 二级缓存是SqlSessionFactory级别&#xff0c;通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存&#xff1b;此后若再次执行相同的查询语句&#xff0c;结果就会从缓存中获取。 二级缓存开启的条件&#xff1a; 1.在核心配置文件中&#x…

软件测试:写一个好的测试用例

测试场景&#xff1a; 为登录功能设计测试用例 测试员为什么要会编测试用例 测试员的目标是要保证系统在各种场景下的功能是符合设计要求的。而测试用例就是测试员想到的测试场景。&#xff08;这也是高级别的测试员即使不会代码也能找到较好工作的原因&#xff09; 编写测试…

数据库2,DQL数据查询语言,表关联关系

目录 DQL数据查询语言 简单查询语句 计算列 别名 distinct消除重复行 条件查询 条件运算符 null值判断 枚举查询 模糊查询 分支查询 函数 字符串函数 聚合函数 排序查询 分组查询Group by 分页查询Limit 表关联关系 一对一关联 一对多与多对一 多对多关联 …

[CKA备考实验][ingress-nginx] 4.2 集群外访问POD

1.创建Deployments 部署方法请参照&#xff1a; https://blog.csdn.net/qq_33868661/article/details/127505429?spm1001.2014.3001.5501 apiVersion: apps/v1 kind: Deployment metadata:labels:name: deploy1annotations:name: deploy1name: deploy1namespace: default sp…

要么干要么滚!推特开始裁员了;深度学习产品应用·随书代码;可分离各种乐器音源的工具包;Transformer教程;前沿论文 | ShowMeAI资讯日报

&#x1f440;日报合辑 | &#x1f4c6;电子月刊 | &#x1f369;韩信子 &#x1f4e2; 解散Twitter董事会&#xff0c;代码审查&#xff0c;裁员25%&#xff0c;收每月20美元认证费马斯克那些骚操作 埃隆马斯克 (Elon Musk) 抱着洗手池入主 Twitter 后&#xff0c;狂风骤雨已…

STM32入门——uKeil5 MDK 的使用(基于固件库)

文章目录1 Keil uVision5 MDK 是什么2 建立一个标准库函数工程2.1 前期准备2.2 建立工程2.3 建立组文件夹2.4 添加文件2.4 配置“魔术棒”选项卡2.5 建立 main 函数1 Keil uVision5 MDK 是什么 Keil 软件是一种统称&#xff0c;它包含编辑器、编译器、链接器、调试器等众多工具…

冰冰学习笔记:二叉搜索树

欢迎各位大佬光临本文章&#xff01;&#xff01;&#xff01; 还请各位大佬提出宝贵的意见&#xff0c;如发现文章错误请联系冰冰&#xff0c;冰冰一定会虚心接受&#xff0c;及时改正。 本系列文章为冰冰学习编程的学习笔记&#xff0c;如果对您也有帮助&#xff0c;还请各位…

堆外内存和堆内内存及虚引用的应用

目录 内存区域划分&#xff1a; 元空间 程序计数器 直接内存 对象的创建 对象的访问定位 判断对象是否存活 堆外内存 堆内内存的缺点以及引入堆外内存 为什么需要堆外内存&#xff1f; 如何分配堆外内存&#xff1f; 如何回收堆外内存&#xff1f; 1) System.gc()…

C语言函数章--第二弹(让冤种室友用你的函数,但不给他看函数源码)

前言 &#x1f496;作者&#xff1a;龟龟不断向前 ✨简介&#xff1a;宁愿做一只不停跑的慢乌龟&#xff0c;也不想当一只三分钟热度的兔子。 &#x1f47b;专栏&#xff1a;C初阶知识点 &#x1f47b;工具分享&#xff1a; 刷题&#xff1a; 牛客网 leetcode笔记软件&#xff…

Error注入攻击

&#x1f4aa;&#x1f4aa;Error注入攻击1.创建漏洞环境2.漏洞攻击2.1判断是否有注入2.2信息收集2.3注入获取数据库名2.4注入获取表名2.5注入获取列名2.6注入获取信息3.sql靶场实战1.创建漏洞环境 &#x1f4aa;&#x1f4aa;第一步创建sql环境&#xff0c;直接再mysql下运行 …

Flutter——软件安装与环境配置

Flutter入门官网Flutter SDK下载创建Flutter项目在ios上运行第一个Flutter项目效果图代码总结官网 Flutter开发手册网址如下 Flutter SDK下载 下载地址 第一步&#xff1a;进入官网&#xff0c;选择自己相对应的系统 第二步&#xff1a;选择对应版本SDK并下载到本地 创建Flu…

electron调用dll文件

Electron 对系统层能力的使用可能比较弱&#xff0c;此时需要求助 Python、C、C# 等语言&#xff0c;通过 ffi-napi 库可以让 Node.js 使用 C dll&#xff0c;通过 electron-edge-js 库可以让 Node.js 使用 C# dll 1. 先确定dll文件是用什么语言写的. 使用peid 应用查看- 这个…

【Transformers】第 2 章:主题的实践介绍

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

Node.js | 基于 MongoDB 的简易用户管理系统

&#x1f5a5;️ NodeJS专栏&#xff1a;Node.js从入门到精通 &#x1f5a5;️ 博主的前端之路&#xff08;源创征文一等奖作品&#xff09;&#xff1a;前端之行&#xff0c;任重道远&#xff08;来自大三学长的万字自述&#xff09; &#x1f5a5;️ TypeScript知识总结&…

C++秋招经验贴

文章目录一、个人背景及秋招情况1.个人背景2.秋招情况二、求职C强相关开发岗位的准备过程以及一些建议1. 八股2. 力扣刷题3. 实习4. 项目三、总结一、个人背景及秋招情况 1.个人背景 本科&#xff1a;二本&#xff0c;材料专业   硕士&#xff1a;211硕&#xff0c;光学工程…

TI IWR1642毫米波雷达使用串口原始数据采集与分析

本文编辑&#xff1a;调皮哥的小助理 1.引言 如果文章能够给你带来价值&#xff0c;希望能够关注我。 如果文章能够让你学习到知识&#xff0c;希望你能够点个赞&#xff01; 好了下面开始今天的学习内容吧。 今天给大家分享的是 《TI 的IWR1642毫米波雷达使用串口原始数据…

深度学习入门(十五)环境和分布偏移(了解)

深度学习入门&#xff08;十五&#xff09;环境和分布偏移前言环境和分布偏移教材1 分布偏移的类型1.1 协变量偏移1.2 标签偏移1.3 概念偏移2 分布偏移示例2.1医学诊断2.2 自动驾驶汽车2.3 非平稳分布2.4 更多轶事3 分布偏移纠正3.1 经验风险与实际风险3.2 协变量偏移纠正3.3 标…

MATLAB | 一起来感受数学之美叭

前两天去观摩了MATHWORKS官方举办的Mathematics is beautiful数学之美投票比赛&#xff0c;见到了很多非常惊艳的作品&#xff0c;在这里分享给大家让大家一同感受大神们的创造力&#xff0c;接下来由我来做全程解说。 虽然看起来代码都写好了&#xff0c;&#xff0c;&#x…

程序员眼中看到的网页是如何制作出来的?

一、认识网页 在学习之初&#xff0c;我们需要认识一下网页的概念&#xff0c;因为网页与我们的 html是息息相关的。 那么接下来我们来看一下&#xff0c;我们经常去通过浏览器查看的网页&#xff0c;它的本质是什么&#xff1f;在此我们需要去做一个对比。我们眼中看到的网页…

聚类算法概要及相关知识准备

聚类的概念 聚类分析是在数据中发现数据对象之间的关系&#xff0c;将数据进行分组&#xff0c;组内的相似性越大&#xff0c;组间的差别越大&#xff0c;则聚类效果越好。 将物理或抽象对象的集合分成由类似对象组成的多个类或簇&#xff08;cluster&#xff09;的过程被称为…