【Netty】编解码器

目录

  • Java的编解码
  • Netty编解码器
    • 概念
    • 解码器(Decoder)
    • 编码器(Encoder)
    • 编码解码器Codec

Java的编解码

编码(Encode)称为序列化, 它将对象序列化为字节数组,用于网络传输、数据持久化或者其它用途。

解码(Decode)称为反序列化,它把从网络、磁盘等读取的字节数组还原成原始对象(通常是原始对象的拷贝),以方便后续的业务逻辑操作。

在这里插入图片描述

java序列化对象只需要实现java.io.Serializable接口并生成序列化ID,这个类就能够通过java.io.ObjectInput和java.io.ObjectOutput序列化和反序列化。

Java序列化目的:1.网络传输。2.对象持久化。

Java序列化缺点:1.无法跨语言。 2.序列化后码流太大。3.序列化性能太低。

Java序列化仅仅是Java编解码技术的一种,由于它的种种缺陷,衍生出了多种编解码技术和框架,这些编解码框架实现消息的高效序列化。

Netty编解码器

概念

在网络应用中需要实现某种编解码器,将原始字节数据与自定义的消息对象进行互相转换。网络中都是以字节码的数据形式来传输数据的,服务器编码数据后发送到客户端,客户端需要对数据进行解码。

对于Netty而言,编解码器由两部分组成:编码器、解码器。

  • 解码器:负责将消息从字节或其他序列形式转成指定的消息对象。
  • 编码器:将消息对象转成字节或其他序列形式在网络上传输。

Netty 的编(解)码器实现了 ChannelHandlerAdapter,也是一种特殊的 ChannelHandler,所以依赖于 ChannelPipeline,可以将多个编(解)码器链接在一起,以实现复杂的转换逻辑。

解码器负责处理“入站 InboundHandler”数据。 编码器负责“出站OutboundHandler” 数据。

解码器(Decoder)

解码器负责解码“入站”数据从一种格式到另一种格式,解码器处理入站数据是抽象ChannelInboundHandler的实现。需要将解码器放在ChannelPipeline中。对于解码器,Netty中主要提供了抽象基类ByteToMessageDecoderMessageToMessageDecoder

在这里插入图片描述

抽象解码器

  • ByteToMessageDecoder: 用于将字节转为消息,需要检查缓冲区是否有足够的字节
  • ReplayingDecoder: 继承ByteToMessageDecoder,不需要检查缓冲区是否有足够的字节,但是 ReplayingDecoder速度略慢于ByteToMessageDecoder,同时不是所有的ByteBuf都支持。项目复杂性高则使用ReplayingDecoder,否则使用ByteToMessageDecoder
  • MessageToMessageDecoder: 用于从一种消息解码为另外一种消息(例如POJO到POJO)

核心方法:

decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out)

示例:

在入门案例的代码基础上进行改造

  1. 解码器

添加解码器

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.util.CharsetUtil;import java.nio.ByteBuffer;
import java.util.List;public class MessageDecoder extends MessageToMessageDecoder {@Overrideprotected void decode(ChannelHandlerContext channelHandlerContext, Object o, List list) throws Exception {System.out.println("正在进行消息解码....");ByteBuffer byteBuffer = (ByteBuffer) o;list.add(byteBuffer.toString());}
}
  1. 通道读取方法

修改NettyServerHandler的通道读取事件,不需要我们手动解码了,直接读取即可,代码如下:r

/*** 通道读取事件** @param channelHandlerContext* @param o* @throws Exception*/
@Override
public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {System.out.println("客户端发送过来的消息:" + o);
}

对应的客户端的NettyClientHandler的通道读就绪事件也修改:

/*** 通道读就绪事件** @param channelHandlerContext* @param o* @throws Exception*/
@Override
public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {System.out.println("服务端发送的消息:" + o);
}
  1. 启动类

向pipeline中添加自定义业务处理handler时,把解码器添加进去,注意添加顺序,解码器要放在第一个,以服务端为例,代码如下:

serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) //5. 设置服务端通道实现为NIO.option(ChannelOption.SO_BACKLOG, 128) //6. 参数设置:初始化服务器可连接队列大小.childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE) //6. 参数设置: 一直保持连接活动状态.childHandler(new ChannelInitializer<SocketChannel>() { //7. 创建一个通道初始化对象@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {//8. 向pipeline中添加自定义业务处理handlersocketChannel.pipeline().addLast(new MessageDecoder()); //添加解码器socketChannel.pipeline().addLast(new NettyServerHandler());}});

客户端也添加即可。

编码器(Encoder)

Netty提供了对应的编码器实现MessageToByteEncoderMessageToMessageEncoder,二者都实现ChannelOutboundHandler接口。

在这里插入图片描述

抽象编码器:

  • MessageToByteEncoder: 将消息转化成字节
  • MessageToMessageEncoder: 用于从一种消息编码为另外一种消息(例如POJO到POJO)

核心方法:

encode(ChannelHandlerContext ctx, String msg, List<Object> out)

示例:

  1. 编码器

新加编码器:

package com.cys.netty.codec;import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.util.CharsetUtil;import java.util.List;public class MessageEncoder extends MessageToMessageEncoder<String> {@Overrideprotected void encode(ChannelHandlerContext channelHandlerContext, String s, List<Object> list) throws Exception {System.out.println("消息进行消息编码");list.add(Unpooled.copiedBuffer(s, CharsetUtil.UTF_8));}
}
  1. 消息发送

修改NettyServerHandler里的通道读取完毕事件,直接发送数据,无序再编码,代码如下:

/*** 通道读取完毕事件** @param channelHandlerContext* @throws Exception*/
@Override
public void channelReadComplete(ChannelHandlerContext channelHandlerContext) throws Exception {// 消息出站channelHandlerContext.writeAndFlush("你好.我是Netty服务端");
}

同样修改NettyClientHandler里的通道就绪事件方法,直接发送数据,无序再编码,代码如下:

/*** 通道就绪事件** @param channelHandlerContext* @throws Exception*/
@Override
public void channelActive(ChannelHandlerContext channelHandlerContext) throws Exception {ChannelFuture future = channelHandlerContext.writeAndFlush("你好呀.我是Netty客户端");future.addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture channelFuture) throws Exception {if (channelFuture.isSuccess()) {System.out.println("数据发送成功!");} else {System.out.println("数据发送失败!");}}});
}
  1. 启动类

向pipeline中添加自定义业务处理handler,添加解码器和编码器,以客户端为例,代码如下:

bootstrap.group(group).channel(NioSocketChannel.class) //4. 设置客户端通道实现为NIO.handler(new ChannelInitializer<SocketChannel>() { //5. 创建一个通道初始化对象@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {//6. 向pipeline中添加自定义业务处理handlersocketChannel.pipeline().addLast(new MessageDecoder()); //添加解码器socketChannel.pipeline().addLast(new MessageEncoder());  //添加编码器socketChannel.pipeline().addLast(new NettyClientHandler());}});

同时服务端也可以加即可。

编码解码器Codec

编码解码器: 同时具有编码与解码功能,特点同时实现了ChannelInboundHandler和ChannelOutboundHandler接口,因此在数据输入和输出时都能进行处理。

在这里插入图片描述

Netty提供提供了一个ChannelDuplexHandler适配器类,编码解码器的抽象基类ByteToMessageCodec ,MessageToMessageCodec都继承与此类。

示例:

  1. 编解码器

新加编解码器,继承MessageToMessageCodec,代码如下:

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import io.netty.util.CharsetUtil;import java.util.List;public class MessageCoder extends MessageToMessageCodec {@Overrideprotected void encode(ChannelHandlerContext channelHandlerContext, Object o, List list) throws Exception {System.out.println("正在进行消息编码");String str = (String) o;list.add(Unpooled.copiedBuffer(str, CharsetUtil.UTF_8));}@Overrideprotected void decode(ChannelHandlerContext channelHandlerContext, Object o, List list) throws Exception {System.out.println("正在进行消息解码");ByteBuf byteBuf = (ByteBuf) o;list.add(byteBuf.toString(CharsetUtil.UTF_8));}
}
  1. 启动类

向pipeline中添加自定义业务处理handler,只添加上面一个编解码器即可:

服务端:

serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) //5. 设置服务端通道实现为NIO.option(ChannelOption.SO_BACKLOG, 128) //6. 参数设置:初始化服务器可连接队列大小.childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE) //6. 参数设置: 一直保持连接活动状态.childHandler(new ChannelInitializer<SocketChannel>() { //7. 创建一个通道初始化对象@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {//8. 向pipeline中添加自定义业务处理handler// socketChannel.pipeline().addLast(new MessageDecoder()); //添加解码器// socketChannel.pipeline().addLast(new MessageEncoder());  //添加编码器socketChannel.pipeline().addLast(new MessageCoder());  //添加编解码器socketChannel.pipeline().addLast(new NettyServerHandler());}});

客户端:

bootstrap.group(group).channel(NioSocketChannel.class) //4. 设置客户端通道实现为NIO.handler(new ChannelInitializer<SocketChannel>() { //5. 创建一个通道初始化对象@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {//6. 向pipeline中添加自定义业务处理handler// socketChannel.pipeline().addLast(new MessageDecoder()); //添加解码器// socketChannel.pipeline().addLast(new MessageEncoder());  //添加编码器socketChannel.pipeline().addLast(new MessageCoder());  //添加编解码器socketChannel.pipeline().addLast(new NettyClientHandler());}});

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

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

相关文章

Python量化投资——金融数据最佳实践: 使用qteasy+tushare搭建本地金融数据仓库并定期批量更新【附源码】

用qteasytushare实现金融数据本地化存储及访问 目的什么是qteasy什么是tushare为什么要本地化使用qteasy创建本地数据仓库qteasy支持的几种本地化仓库类型配置本地数据仓库配置tushare 的API token 配置本地数据源 —— 用MySQL数据库作为本地数据源下载金融历史数据 数据的定期…

基于多反应堆的高并发服务器【C/C++/Reactor】(中)

在这篇文章中虽然实现了能够和多客户端建立连接&#xff0c;并且同时和多个客户端进行通信。 基于多反应堆的高并发服务器【C/C/Reactor】&#xff08;上&#xff09;-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/135141316?spm1001.2014.3001.5501但是有…

SuperMap Hi-Fi 3D SDK for Unity基础开发教程

作者&#xff1a;kele 一、背景 众所周知&#xff0c;游戏引擎&#xff08;Unity&#xff09;功能强大&#xff0c;可以做出很多炫酷的游戏和动画效果&#xff0c;这部分功能的实现往往不仅仅是靠可视化界面就能够实现的&#xff0c;还需要代码开发。SuperMap Hi-Fi SDKS for …

清风数学建模笔记-插值算法

内容&#xff1a;插值算法 概念&#xff1a; 二.种类 1.牛顿插值法&#xff0c;拉格朗日插值法&#xff0c;两者容易出现龙格现象 2.分段线性插值&#xff1a;与上面两种相比要更好一些,原理是两线之间构成一条直线&#xff0c;在这条直线上插值&#xff0c;除此之外还有分段…

读算法霸权笔记01_数学杀伤性武器

1. 数学应用助推数据经济&#xff0c;但这些应用的建立是基于不可靠的人类所做的选择 1.1. 房地产危机&#xff0c;大型金融机构倒闭&#xff0c;失业率上升&#xff0c;在幕后运用着神奇公式的数学家们成为这些灾难的帮凶 1.2. 数学逐渐不再关注全球金融市场动态&#xff0c…

用Python处理PDF:拆分与合并PDF文档

PDF文档在信息共享和数据保存方面被广泛使用&#xff0c;处理PDF文档也成为常见需求。其中&#xff0c;合并和拆分PDF文档能够帮助我们更有效地管理PDF文档&#xff0c;使文档内容分布更合理。通过合并&#xff0c;可以将相关文档整合成一个文件&#xff0c;以便更好地组织和提…

LeetCode394.字符串解码

这道题有点像我之前写过的一道题有效的括号&#xff08;不只是栈&#xff09;-CSDN博客 但是比那道题要难&#xff0c;但用的方法是一样的&#xff0c;就是用栈的先进后出进行括号匹配&#xff0c;所以有写过之前那道题&#xff0c;这道题按照这个思路走我就写出了如下屎山代码…

使用宝塔面板部署前端项目到服务器

目录 文章目录 前言 一、第一步&#xff1a;创建文件夹 二、第二步&#xff1a;部署前端项目 三、第三步&#xff1a;打开防火墙 文章目录 前言第一步&#xff1a;创建文件夹第二步&#xff1a;部署前端项目第三步&#xff1a;打开防火墙总结 前言 在此之前&#xff0c;我…

智能优化算法应用:基于鹰栖息算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于鹰栖息算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于鹰栖息算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.鹰栖息算法4.实验参数设定5.算法结果6.参考文…

DHorse v1.5.0 发布,基于 k8s 的发布平台

版本说明 新增特性 支持同一机器部署多个DHorse服务&#xff1b;支持Next、.NET应用部署&#xff1b;优化Node、Nuxt应用构建和部署的性能&#xff1b;默认使用fabric8客户端与k8s集群交互&#xff0c;可以通过指定参数-Dkubernetes-clientofficial切回到k8s官方客户端&#…

亚马逊推出 Graviton4:具有 536.7 GBps 内存带宽的 96 核 ARM CPU

如今&#xff0c;许多云服务提供商都设计自己的芯片&#xff0c;但亚马逊网络服务 (AWS) 开始领先于竞争对手&#xff0c;目前其子公司 Annapurna Labs 开发的处理器可以与 AMD 和英特尔的处理器竞争。本周&#xff0c;AWS 推出了 Graviton4 SoC&#xff0c;这是一款基于 ARM 的…

【Filament】绘制圆形

1 前言 Filament环境搭建中介绍了 Filament 的 Windows 和 Android 环境搭&#xff0c;绘制三角形中介绍了绘制纯色和彩色三角形&#xff0c;绘制矩形中介绍了绘制纯色和彩色矩形&#xff0c;本文将使用 Filament 绘制圆形。 2 绘制圆形 本文项目结构如下&#xff0c;完整代码…

RetinaNet:Focal Loss for Dense Object Detection(CVPR2018)

文章目录 Abstract北京发现问题并给出方法成果 IntroductionRelated WorkRobust 评估 Focal LossBalanced Cross EntropyFocal Loss DefinitionClass Imbalance and Model InitializationClass Imbalance and Two-stage Detectors RetinaNet DetectorExperimentsConclusion hh …

基于SpringBoot的桃花峪滑雪场租赁系统 JAVA简易版

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 游客服务2.2 雪场管理 三、数据库设计3.1 教练表3.2 教练聘请表3.3 押金规则表3.4 器材表3.5 滑雪场表3.7 售票表3.8 器材损坏表 四、系统展示五、核心代码5.1 查询教练5.2 教练聘请5.3 查询滑雪场5.4 滑雪场预定5.5 新…

WebAssembly 的魅力:高效、安全、跨平台(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

JUC并发编程 08——原子操作类

目录 一.原子更新基本类型类 实现原理 二.原子更新数组 三.原子更新引用类型 四.原子更新字段类 Java从JDK1.5开始提供了J.U.C下的atomic包&#xff0c;atomic包提供了一系列的操作简单&#xff0c;性能高效&#xff0c;并能保证线程安全的类去更新基本类型变量&#xff0…

WebAssembly 的魅力:高效、安全、跨平台(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

Unity中的导航系统

NavMesh(导航网格)是3D游戏世界中用于实现动态物体自动寻路的一种技术&#xff0c;将游戏中复杂的结构组织关系简化为带有一定信息的网格&#xff0c;在这些网格的基础上通过一系列的计算来实现自动寻路。导航时&#xff0c;只需要给导航物体挂载导航组建&#xff0c;导航物体便…

【Grafana】Grafana匿名访问以及与LDAP连接

上一篇文章利用Docker快速部署了Grafana用来展示Zabbix得监控数据&#xff0c;但还需要给用户去创建账号允许他们登录后才能看展示得数据&#xff0c;那有什么办法让非管理员更方便得去访问Grafana呢&#xff1f;下面介绍两个比较方便实现的&#xff1a; 在开始设置前&#xff…

显示器屏幕oled的性能、使用场景、维护

OLED显示器屏幕具有许多独特的性能和使用场景&#xff0c;以下是关于OLED显示器屏幕的性能、使用场景和维护的详细介绍&#xff1a; 一、性能 色彩鲜艳&#xff1a;OLED显示器屏幕能够呈现出更加鲜艳的色彩&#xff0c;色彩饱和度高&#xff0c;色彩还原性好&#xff0c;可以给…