Netty2

news2024/11/24 9:53:15

文章目录

  • Netty2
    • Netty入站与出站机制
    • Netty的handler链的调用机制

Netty2

Netty入站与出站机制

基本说明
1)netty的组件设计:Netty的主要组件有Channel,EventLoop,ChannelFuture,ChannelHandler,ChannelPipe等。
2)ChannelHandler 充当了处理入站和出站数据的应用程序逻辑的容器。例如,实现 ChannelInboundHandler 接口(或 ChannelInboundHandlerAdapter),你就可以接收入站事件和数据,这些数据会被业务逻辑处理。当要给客户端发送响应时,也可以从 ChannelInboundHandler 冲刷数据。业务逻辑通常卸载一个或者多个 ChannelInboundHandler 中。ChannelOutboundHandler 原理一样,只不过它是用来处理出站数据的。
3)ChannelPipeline 提供了 ChannelHandler 链的容器。以客户端应用程序为例,如果事件的运动方向是从客户端到服务端的,那么我们称这些事件为出站的,即客户端发送服务端的数据会通过 pipeline 中的一系列 ChannelOutboundHandler,并被这些 Handler 处理,反之则称为入站的。

在这里插入图片描述

编码解码器
1)当 Netty 发送或者接收一个消息的时候,就将会发生一次数据转换。入站消息会被解码:从字节转换为另一种格式(比如 java 对象);如果是出站消息,它会被编码成字节。
2)Netty 提供一系列实用的编解码器,他们都实现了 ChannelInboundHandler 或者 ChannelOutboundHandler 接口。在这些类中,channelRead 方法已经被重写了。已入站为例,对于每个从入站 Channel 读取的消息,这个方法会被调用。随后,它将调用由解码器所提供的 decode() 方法进行解码,并将已经解码的字节转发给 ChannelPipeline 中的下一个 ChannelInboundHandler。

解码器ByteToMessageDecoder
1)关系继承图,如下图:
在这里插入图片描述
2)由于不可能知道远程节点是否会一次性发送一个完整的信息,tcp有可能出现粘包拆包的问题,这个类会对入站数据进行缓冲,直到它准备好被处理。
3)关于ByteToMessageDecoder实例分析

public class ToIntegerDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        if(in.readableBytes() >= 4){
            out.add(in.readInt());
        }
    }
}

注意ByteToMessageDecoder是一个解码器,除了这个解码器,还有一个编码器叫做MessageToByteEncoder。

实例说明:

  • 这个例子,每次入站从 ByteBuf 读取4字节,将其解码为一个 int,然后将它添加到下一个 List 中。当没有更多元素可以被添加到该 List 中,它的内容将会发送给下一个 ChannelInboundHandler。int 在被添加到 List 中时,会被自动装箱为 Integer。在调用 readInt() 方法前必须验证所输入的 ByteBuf 是否具有足够的数据。
  • decode执行分析图。在这里插入图片描述

Netty的handler链的调用机制

要求:使用自定义的编码器和解码器来说明Netty的handler调用机制。
客户端发送long -> 服务器
服务端发送long->客户端

结果:数据在客户端和服务端之间传输的时候是通过二进制文件的形式传输的。客户端会先调用它的业务处理ClientHandler,然后会调用编码器Handler,接着把数据传输到Socket中,再由Socket把数据传输到服务器中;服务器接收到Socket中的数据之后,会先调用解码器Handler进行解码,然后调用它自己的ServerHandler进行业务处理,接着会把数据返回给客户端,会把这些数据编码,因此会执行编码器Handler,然后把数据传输到Scoket里面,再通过Scoket把数据传输给客户端,客户端拿到数据之后先解码,先调用解码处理器进行解码,然后再调用ClientHandler处理器进行客户端业务处理。整体流程图如下图:
在这里插入图片描述
编码器和解码器代码如下:

/**
 * @author xuan
 * @create 2023/9/19
 * 编码器
 */
public class MyLongToByteEncoder extends MessageToByteEncoder<Long> {
    @Override
    protected void encode(ChannelHandlerContext ctx, Long msg, ByteBuf out) throws Exception {
        System.out.println("MyLongToByteEncoder 的 encode()方法被调用");
        System.out.println("msg = " + msg);
        out.writeLong(msg);
    }
}


/**
 * @author xuan
 * @create 2023/9/19
 * 解码器
 */
public class MyByteToLongDecoder extends ByteToMessageDecoder {
    /**
     * decode 会根据接收的数据,被调用多次,知道确定没有新的元素被添加到list,或者是Bytebuf 没有更多的可读字节为止
     * 如果 list out 不为空,就会将list的内容传递给下一个 channelInboundHandler 处理,该处理器的方法也会被调用多次
     *
     * @param ctx 上下文
     * @param in 入站的 ByteBuf
     * @param out List 集合,将解码后的数据传给下一个 handler 处理
     * @throws Exception
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        System.out.println("MyByteToLongDecoder 的 decode()方法被调用");
        // 因为 long 是 8 个字节,需要判断有 8 个字节,才能读取一个 long
        if(in.readableBytes() >= 8){
            out.add(in.readLong());
        }
    }
}

服务端代码如下:

/**
 * @author xuan
 * @create 2023/9/19
 */
public class MyServer {
    public static void main(String[] args) throws InterruptedException {
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workerGroup = new NioEventLoopGroup(8);

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new MyServerInitializer());

            ChannelFuture channelFuture = serverBootstrap.bind(8080).sync();
            channelFuture.channel().closeFuture().sync();

        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

}
/**
 * @author xuan
 * @create 2023/9/19
 */
public class MyServerInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        // 入站的 handler 进行解码
        pipeline.addLast(new MyByteToLongDecoder());
        pipeline.addLast(new MyLongToByteEncoder());
        pipeline.addLast(new MyServerHandler());
    }
}
/**
 * @author xuan
 * @create 2023/9/19
 */
public class MyServerHandler extends SimpleChannelInboundHandler<Long> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Long msg) throws Exception {
        System.out.println("从客户端" + ctx.channel().remoteAddress() + "读取到的数据到long " + msg);

        // 给客户端发送一个 long
        ctx.writeAndFlush(123L);
    }

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

客户端代码如下:

/**
 * @author xuan
 * @create 2023/9/19
 */
public class MyClient {
    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 MyClientInitializer());

            ChannelFuture channelFuture = bootstrap.connect("localhost", 8080).sync();
            channelFuture.channel().closeFuture().sync();

        }finally {
            group.shutdownGracefully();
        }
    }
}

/**
 * @author xuan
 * @create 2023/9/19
 */
public class MyClientInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        //加入一个出站的handler,对数据进行一个编码
        pipeline.addLast(new MyLongToByteEncoder());
        pipeline.addLast(new MyByteToLongDecoder());
        //加入一个自定义的handler,处理业务逻辑
        pipeline.addLast(new MyClientHandler());
    }
}
/**
 * @author xuan
 * @create 2023/9/19
 */
public class MyClientHandler extends SimpleChannelInboundHandler<Long> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Long msg) throws Exception {
        System.out.println("服务器的ip=" + ctx.channel().remoteAddress());
        System.out.println("服务器回送的消息:" + msg );
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("MyClientHandler 发送数据");
        ctx.writeAndFlush(123456L);

        // 分析
        // 1. "abcdabcdabcdabcd" 是16个字节
        // 2. 该处理器的前一个 handler 是 MyLongToByteEncoder
        // 3. MyLongToByteEncoder 父类是 MessageToByteEncoder
        // 4. 父类 MessageToByteEncoder 中 acceptOutboundMessage(msg) 会判断当前 msg 是不是应该处理的类型,如果是就处理,不是就跳过
        // 5. 编写 Encoder 时要注意传入的数据类型和处理的数据类型需要一致
//        ctx.writeAndFlush(Unpooled.copiedBuffer("abcdabcdabcdabcd", CharsetUtil.UTF_8));
    }
}

几个要点说明,如下图:
在这里插入图片描述
编码的时候直接把Long类型数据写入即可,会自动的转换为byte二进制类型,如下图:
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

[golang gui]fyne框架代码示例

1、下载GO Go语言中文网 golang安装包 - 阿里镜像站(镜像站使用方法&#xff1a;查找最新非rc版本的golang安装包) golang安装包 - 中科大镜像站 go二进制文件下载 - 南京大学开源镜像站 Go语言官网(Google中国) Go语言官网(Go团队) 截至目前&#xff08;2023年9月17日&#x…

中秋猜灯谜小游戏

中秋猜灯谜小游戏是一个基于HTML制作的互动游戏&#xff0c;旨在增添中秋节的欢乐氛围&#xff0c;通过猜灯谜来娱乐和挑战玩家。 目录 前言简介游戏规则 制作过程HTML 结构CSS 样式JavaScript 交互 功能实现题目和答案的存储游戏逻辑设计 前言 简介 游戏开始时&#xff0c;玩…

SpringBoot Admin监控平台《二》基础报警设置

一、前置准备 首先搭建监控一个平台和连个客户端&#xff0c;搭建流程见SpringBoot Admin监控平台《一》平台搭建及基础介绍 &#xff0c;搭建完毕之后&#xff0c;启动各个项目&#xff0c;监控平台的界面如下所示&#xff1a; 二、邮件报警 2.1.邮箱授权码获取 授权码主要…

5.5V-65V Vin同步降压控制器,具有线路前馈SCT82630DHKR

描述&#xff1a; SCT82630是一款65V电压模式控制同步降压控制器&#xff0c;具有线路前馈。40ns受控高压侧MOSFET的最小导通时间支持高转换比&#xff0c;实现从48V输入到低压轨的直接降压转换&#xff0c;降低了系统复杂性和解决方案成本。如果需要&#xff0c;在低至6V的输…

天猫全店商品采集教程,天猫店铺所有商品接口(详解天猫店铺所有商品数据采集步骤方法和代码示例)

随着电商行业的快速发展&#xff0c;天猫已成为国内的电商平台之一&#xff0c;拥有着海量的商品资源。对于一些需要大量商品数据的商家或者需求方来说&#xff0c;天猫全店采集是非常必要的。本文将详细介绍天猫全店采集的步骤和技巧&#xff0c;帮助大家更好地完成数据采集任…

使用Visual Leak Detector排查内存泄漏问题

目录 1、VLD工具概述 2、下载并安装VLD 2.1、下载VLD 2.2、安装VLD 3、VLD安装目录及文件说明 3.1、安装目录及文件说明 3.2、关于32位和64位版本的详细说明 4、在工程中引入VLD 5、内存泄漏检测实例讲解 5.1、程序启动报错 5.2、启动调试&#xff0c;查看内存泄漏报…

二维码生成器

二维码生成器 二维码生成器_二维码在线制作_应用方案提供商_互联二维码 使用方式 先知道自己电脑端口 然后运行你要生成页面 拼接自己的端口和页面路径

四川天蝶电子商务有限公司正规吗?

近年来&#xff0c;随着短视频平台的兴起&#xff0c;抖音成为了中国最受欢迎的社交媒体之一。许多企业看到了抖音带货的巨大商机&#xff0c;纷纷涌入这个领域。然而&#xff0c;一些不法分子也乘机滋生&#xff0c;伪装成合法的商家&#xff0c;进行各种欺诈行为。所以&#…

这些提高摸鱼效率的自动化测试技巧,提高打工人幸福感~

最近有许多小伙伴都在吐槽打工好难。 每天都是执行许多重复的任务 例如阅读新闻、发邮件、查看天气、打开书签、清理文件夹等等&#xff0c; 使用自动化脚本&#xff0c;就无需手动一次又一次地完成这些任务&#xff0c; 非常方便啊有木有&#xff1f;&#xff01; 今天就…

rv1126-rv1109-瑞芯微的 IPC 程序

关闭瑞芯微的 IPC 程序 例程源码中,第一次下载之后会进入一个类似摄像头demo预览的界面 我想要关掉它,找了很久,终于发现 \rv1126_rv1109\buildroot\board\rockchip\rv1126_rv1109\fs-overlay-sysv\etc\init.d\S98_lunch_init 这个文件注解掉全部 就可以看到注解掉就只有l…

软文推广在医疗行业中的优势有哪些?媒介盒子告诉你

随互联网的快速发展&#xff0c;越来越多的企业开始利用网络宣传&#xff0c;医疗行业也参与其中&#xff0c;相比于传统广告的高成本和不明显的效果&#xff0c;软文推广的效果更明显&#xff0c;对医疗行业的宣传帮助也更大&#xff0c;现在就由媒介盒子告诉大家&#xff0c;…

springboot整合mybatis(详解)

springboot整合mybatis 1. 整体架构展示&#xff1a; 2. pom.xml-需要的依赖&#xff1a; <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency&g…

ICS TRIPLEX T8461 PLC系统备件模块

ICS TRIPLEX T8461 是一款用于 PLC&#xff08;可编程逻辑控制器&#xff09;系统备件的模块&#xff0c;通常用于工业自动化和控制系统中。这种类型的备件模块在多个应用领域都有广泛的用途&#xff0c;包括但不限于以下几个领域&#xff1a; 制造业&#xff1a; T8461 模块可…

FastAdmin开发七牛云上传插件

一看官网一个上传插件60大洋&#xff0c;对我这个穷鬼来说还是太贵了&#xff0c;于是乎自己写一个&#xff0c;后面随时用 直接开干 创建插件 php think addon -a aliupload -c create创建配置 <?phpreturn [[name > region,title > 获取存储区域,type > sel…

Linux内核中断(内核中断实现过程、注册三个按键中断实例、中断底半部实例、工作队列)

一、linux内核中断 1.目的&#xff1a; 用于对设备不用进行轮询访问&#xff0c;而是当设备事件发生后主动通知内核&#xff0c;内核再去访问设备。 2.linux内核中断实现过程框图 3.中断子系统API 1.解析中断相关的设备树节点 struct device_node *of_find_compatible_node…

【笔试强训选择题】Day44.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&#xff…

CSS 滚动驱动动画 scroll-timeline ( scroll-timeline-name ❤️ scroll-timeline-axis )

scroll-timelinescroll-timeline-name❤️scroll-timeline-axis 解决问题语法 animation-timeline-nameanimation-timeline-axis scroll-timeline ( scroll-timeline-name ❤️ scroll-timeline-axis ) 在 scroll() 的最后我们遇到了因为定位问题导致滚动效果失效的情况, 当…

选择渲染农场的几个标准

随着电影、电视剧等影视作品的制作越来越依赖于计算机特效&#xff0c;渲染农场的使用也变得越来越普遍。渲染农场是一种利用大量计算机图形处理器&#xff08;GPU&#xff09;来加速渲染过程的服务。在选择渲染农场时&#xff0c;有几个标准可以帮助您确定哪个农场是适合您的项…

图神经网络系列之消息传递

文章目录 1.前言2.消息传递机制1.RecGNN2.ConvGNNs3.GAT 1.前言 相比较于神经网络最基本的网络结构全连接层&#xff08;MLP&#xff09;&#xff0c;特征矩阵乘以权重矩阵&#xff0c;图神经网络多了一个邻接矩阵。计算形式很简单&#xff0c;三个矩阵相乘再加上一个非线性变…

rv1126-rv1109-编译的剖析

./build.sh uboot:cmds./build.sh ubootcd u-boot make rv1126_defconfig make menuconfig ### 保存配置到对应的⽂件rv1126_defconfig make savedefconfig cp defconfig configs/rv1126_defconfig //剖析 ./build.sh uboot //调用 ./mk-loader.sh build.sh -> mk-all.sh …