Netty Review - StringEncoder字符串编码器和StringDecoder 解码器的使用与源码解读

文章目录

  • 概念
  • 概述
    • StringEncoder
    • StringDecoder
  • Code
  • 源码分析
    • StringEncoder
    • StringDecoder
  • 小结

在这里插入图片描述


概念

在这里插入图片描述


概述

Netty是一个高性能的网络应用程序框架,它提供了丰富的功能,包括编解码器,这些编解码器用于在网络中发送和接收数据时进行数据的编码和解码。

在Netty中,StringEncoderStringDecoder是两个常用的编解码器,它们的功能和用途如下:

  1. StringEncoder
    • 功能StringEncoder是一个字符编码器,它将字符串(String)数据转换为字节数组(byte[])。
    • 用途:在网络通信中,数据传输是以字节流的形式进行的,因此,当需要发送文本数据时,需要将字符串转换为字节。StringEncoder就是执行这种转换的组件。
    • 工作方式:它使用指定的字符集(如UTF-8)将字符串编码为字节。
  2. StringDecoder
    • 功能StringDecoder是一个字符解码器,它将接收到的字节数组(byte[])数据转换为字符串(String)。
    • 用途:当服务器或客户端接收到字节流数据时,需要将这些字节解码为文本格式,以便进行进一步处理。StringDecoder就是用来完成这个任务的。
    • 工作方式:它使用指定的字符集(如UTF-8)将字节解码为字符串。

Netty 中的 StringEncoderStringDecoder 是专门用于处理字符串数据的编码和解码器。这两个组件可以简化字符串在网络中的传输过程,让开发者能够更加方便地处理文本数据。

StringEncoder

StringEncoder 是一个将字符串编码为字节流的组件。在 Netty 的 pipeline 中,当你需要将字符串发送到网络时,你可以使用 StringEncoder 来实现。它会将字符串转换为字节流,以便可以在网络中传输。
例如,当你使用 Netty 的 Bootstrap 类来配置你的客户端时,你可以为你的 channel pipeline 添加一个 StringEncoder

Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new StringEncoder());// 添加其他 handlers...}});

在这个例子中,StringEncoder 被添加到了 channel 的 pipeline 中,这样在数据传输过程中,发送的字符串就会被自动编码为字节流。


StringDecoder

StringEncoder 相对应,StringDecoder 是用于将接收到的字节流解码为字符串的组件。当你在 Netty 的 pipeline 中接收到字节流时,你可以使用 StringDecoder 来自动将字节流转换为字符串。

继续上面的例子,如果你想在 pipeline 中添加 StringDecoder,你可以这样做:

Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new StringDecoder());// 添加其他 handlers...}});

在这个例子中,StringDecoder 被添加到了 channel 的 pipeline 中,这样在数据接收过程中,接收到的字节流就会被自动解码为字符串。
总的来说,StringEncoderStringDecoder 是 Netty 中专门用于处理字符串数据的编码和解码器,它们简化了字符串在网络中的传输过程,让开发者能够更加方便地处理文本数据。


Code

在这里插入图片描述

 package com.artisan.codec.stringencoder;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
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;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class NettyServer {// Netty服务器的主方法public static void main(String[] args) throws Exception {// 创建boss线程组,用于接受客户端连接EventLoopGroup bossGroup = new NioEventLoopGroup(1);// 创建worker线程组,用于进行SocketChannel的数据读写EventLoopGroup workerGroup = new NioEventLoopGroup();try {// 创建ServerBootstrap,它是Netty服务端的启动助手ServerBootstrap serverBootstrap = new ServerBootstrap();// 绑定线程组到ServerBootstrapserverBootstrap.group(bossGroup, workerGroup)// 指定使用NioServerSocketChannel接受进来的连接.channel(NioServerSocketChannel.class)// 设置子通道处理器.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 获取通道的管道ChannelPipeline pipeline = ch.pipeline();// 添加字符串解码器pipeline.addLast(new StringDecoder());// 添加自定义的处理器pipeline.addLast(new NettyServerHandler());}});// 打印服务启动信息System.out.println("netty server start。。");// 绑定端口号,并同步等待成功,即启动服务端ChannelFuture channelFuture = serverBootstrap.bind(1234).sync();// 等待服务器socket关闭channelFuture.channel().closeFuture().sync();} finally {// 优雅地关闭boss线程组bossGroup.shutdownGracefully();// 优雅地关闭worker线程组workerGroup.shutdownGracefully();}}
}
package com.artisan.codec.stringencoder;import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class NettyServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println("从客户端读取到String:" + msg.toString());}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}

这段代码是一个简单的Netty服务器启动类,其中包括了启动Netty服务器的所有必要步骤。代码中包含了中文注释,对每一部分的功能都做了简单解释。


package com.artisan.codec.stringencoder;import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class NettyServerHandler extends ChannelInboundHandlerAdapter {// 当读取到客户端发送的消息时,会调用此方法@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {// 打印从客户端读取到的字符串消息System.out.println("从客户端读取到String:" + msg.toString());}// 当发生异常时,会调用此方法@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {// 打印异常堆栈信息cause.printStackTrace();// 关闭通道ctx.close();}
}

package com.artisan.codec.stringencoder;import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class NettyClient {// Netty客户端的主方法public static void main(String[] args) throws Exception {// 创建事件循环组EventLoopGroup group = new NioEventLoopGroup();try {// 创建Bootstrap,它是Netty客户端的启动助手Bootstrap bootstrap = new Bootstrap();// 绑定事件循环组到Bootstrapbootstrap.group(group).channel(NioSocketChannel.class)// 设置通道初始化处理器.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 获取通道的管道ChannelPipeline pipeline = ch.pipeline();// 添加字符串编码器pipeline.addLast(new StringEncoder());// 添加自定义的处理器pipeline.addLast(new NettyClientHandler());}});// 打印客户端启动信息System.out.println("netty client start。。");// 连接到服务器,同步等待成功,即启动客户端ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 1234).sync();// 等待客户端socket关闭channelFuture.channel().closeFuture().sync();} finally {// 优雅地关闭事件循环组group.shutdownGracefully();}}
}

这段代码是一个简单的Netty客户端启动类,其中包括了启动Netty客户端的所有必要步骤。代码中包含了中文注释,对每一部分的功能都做了简单解释。

package com.artisan.codec.stringencoder;import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;/*** @author 小工匠* @version 1.0* @mark: show me the code , change the world*/
public class NettyClientHandler extends ChannelInboundHandlerAdapter {// 当从服务器接收到消息时,会调用此方法@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {// 打印接收到的服务器消息System.out.println("收到服务器消息:" + msg);}// 当通道激活时,会调用此方法@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {// 定义要发送的字符串消息String msg = "字符串消息";// 打印发送消息的日志信息System.out.println("NettyClientHandler发送数据:" + msg);// 向服务器发送消息ctx.writeAndFlush(msg);}
}

这段代码是一个自定义的Netty客户端处理器,继承自ChannelInboundHandlerAdapter。其中包括了两个重写的方法,channelRead和channelActive,分别用于处理服务器消息的读取和通道激活时发送消息。代码中包含了中文注释,对每一部分的功能都做了简单解释


【测试结果】

在这里插入图片描述
在这里插入图片描述


源码分析

在这里插入图片描述

StringEncoder

// StringEncoder类继承自MessageToMessageEncoder,用于将字符序列(CharSequence)消息转换为另一个消息类型
@Sharable
public class StringEncoder extends MessageToMessageEncoder<CharSequence> {// 用于编码的字符集private final Charset charset;/*** 使用当前系统的默认字符集创建一个新的实例。*/public StringEncoder() {this(Charset.defaultCharset());}/*** 使用指定的字符集创建一个新的实例。*/public StringEncoder(Charset charset) {this.charset = ObjectUtil.checkNotNull(charset, "charset");}// 重写父类的encode方法,实现字符序列到字节的转换@Overrideprotected void encode(ChannelHandlerContext ctx, CharSequence msg, List<Object> out) throws Exception {// 如果字符序列为空,则直接返回if (msg.length() == 0) {return;}// 使用ByteBufUtil.encodeString方法将字符序列编码为字节,并使用ctx.alloc()分配内存缓冲区// 然后将编码后的字节添加到输出列表out中,以便后续处理out.add(ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(msg), charset));}
}
  1. 类继承关系

    • StringEncoder继承自MessageToMessageEncoder<CharSequence>,后者又继承自ChannelOutboundHandlerAdapterMessageToMessageEncoder接口用于将消息对象转换为另一个消息对象,而这里的参数CharSequence表示输入的消息对象类型,即字符序列。
      在这里插入图片描述
  2. 构造函数

    • StringEncoder():默认构造函数,使用默认字符集(UTF-8)。
    • StringEncoder(Charset charset):指定字符集的构造函数。这里使用了ObjectUtil.checkNotNull方法来检查字符集是否为空,保证字符集的有效性。
  3. 核心方法

    • encode(ChannelHandlerContext ctx, CharSequence msg, List<Object> out):将字符序列消息编码为字节。这个方法重写了MessageToMessageEncoder接口的encode方法。
    • 在编码过程中,首先检查字符序列是否为空,如果为空,则直接返回。
    • 使用ByteBufUtil.encodeString方法将字符序列编码为字节,并使用ctx.alloc()分配内存缓冲区。
    • 将编码后的字节添加到输出列表out中,以便后续处理。
  4. 异常处理

    • encode方法中,如果发生异常,会抛出异常。
      通过以上分析,我们可以看出StringEncoder的主要作用是将字符序列消息编码为字节。它利用指定的字符集进行编码,并在异常情况下抛出异常。这段代码简洁明了,实现了字符串编码的核心功能。

StringDecoder

/*** 字符串解码器,继承自Netty的MessageToMessageDecoder,用于将ByteBuf消息解码为字符串消息。*/
@Sharable
public class StringDecoder extends MessageToMessageDecoder<ByteBuf> {// 字符集解码器,用于解码ByteBuf中的数据为字符串private final Charset charset;/*** 使用默认的系统字符集创建一个新的解码器实例。*/public StringDecoder() {this(Charset.defaultCharset());}/*** 使用指定的字符集创建一个新的解码器实例。*/public StringDecoder(Charset charset) {this.charset = ObjectUtil.checkNotNull(charset, "charset");}/*** 重写decode方法,将ByteBuf中的数据解码为字符串,并添加到解码消息列表中。*/@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {// 将ByteBuf转换为字符串,并使用指定的字符集解码out.add(msg.toString(charset));}
}

StringDecoder是Netty网络通信框架中的一个解码器,用于将接收到的字节缓冲区(ByteBuf)解码为字符串。下面是对StringDecoder源码的分析:

  1. 类定义:StringDecoder继承自MessageToMessageDecoder,并实现了Sharable接口。Sharable接口主要用于实现解码器的共享,表示同一个解码器实例可以在不同的ChannelHandlerContext中使用。
@Sharable
public class StringDecoder extends MessageToMessageDecoder<ByteBuf> {

在这里插入图片描述

  1. 字段定义:StringDecoder类中有一个私有字段charset,它表示用于解码的字符集。
private final Charset charset;
  1. 构造函数:StringDecoder类有两个构造函数,一个是无参构造函数,另一个是带有字符集参数的构造函数。无参构造函数会使用系统默认的字符集创建解码器实例,而有参构造函数允许用户指定字符集。
public StringDecoder() {this(Charset.defaultCharset());
}
public StringDecoder(Charset charset) {this.charset = ObjectUtil.checkNotNull(charset, "charset");
}
  1. decode方法:decode方法是MessageToMessageDecoder类的一个抽象方法,用于实现具体的解码逻辑。在StringDecoder中,它将接收到的字节缓冲区(ByteBuf)转换为字符串,并使用指定的字符集进行解码。最后,将解码后的字符串添加到解码消息列表中。
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {out.add(msg.toString(charset));
}

总结:StringDecoder是Netty中的一个解码器,用于将接收到的字节缓冲区(ByteBuf)解码为字符串。它提供了两个构造函数,允许用户指定字符集。在decode方法中,它将ByteBuf转换为字符串,并使用指定的字符集进行解码,将解码后的字符串添加到解码消息列表中。


小结

在Netty的通道处理器(ChannelHandler)中,StringEncoderStringDecoder通常以管道(Pipeline)的形式添加到通道(Channel)中,这样,在数据传输过程中,发送的数据会被StringEncoder编码,接收的数据会被StringDecoder解码。通过这种方式,Netty保证了字符串数据在网络中的高效传输和正确解析。

简而言之,StringEncoderStringDecoder是Netty中处理字符串数据编解码的关键组件,它们让字符串数据可以在网络中安全、准确地传输。
在这里插入图片描述

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

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

相关文章

SOME/IP SubscriberEventGroup

1 SOME/IP SubscriberEventGroup SubscriberEventGroup是SOME/IP中的一种服务发现和注册的消息类型,它用于让服务使用者订阅服务提供者的事件组。 事件组是一种将服务的方法和字段分组的方式,它可以让服务使用者只接收感兴趣的数据,而不是所有的数据。 SubscriberEventGrou…

nodejs+vue+微信小程序+python+PHP柚子校园影院系统-计算机毕业设计推荐

柚子校园影院综合网络空间开发设计要求。目的是将系统传统管理方式转换为在网上管理&#xff0c;完成信息管理的方便快捷、安全性高、交易规范做了保障&#xff0c;目标明确。柚子校园影院可以将功能划分为管理员功能和用户功能。  而开发本系统&#xff0c;又能够提高系统整体…

在 Windows 搭建 SVN 服务

近公司给配了台新电脑&#xff0c;配置挺主流的&#xff0c;但是不舍得抛弃自己的旧电脑&#xff08;原配嘛&#xff0c;这叫贪新不舍旧&#xff09;&#xff0c;于是打算在新电脑上只作开发环境&#xff0c;然后旧电脑作为版本库&#xff0c;这样保存版本的时候可以直接上传到…

es、MySQL 深度分页问题

文章目录 es 深度分页MySQL 深度分页 es 深度分页 es 深度分页问题&#xff0c;有点忘记了&#xff0c;这里记录一下 当索引库中有10w条数据&#xff0c;比如是商品数据&#xff1b;用户就是要查在1w到后10条数据&#xff0c;怎么查询。 es查询是从各个分片中取出前1w到后10条数…

LeetCode 19 删除链表的倒数第 N 个结点

题目描述 删除链表的倒数第 N 个结点 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1…

列举mfc140u.dll丢失的解决方法,常见的mfc140u.dll问题

在使用电脑的过程中&#xff0c;有时会遇到mfc140u.dll文件丢失的问题&#xff0c;导致一些应用程序无法正常启动。本文将介绍mfc140u.dll丢失的常见原因&#xff0c;并提供相应的解决办法。同时&#xff0c;还会列举一些与mfc140u.dll丢失相关的常见问题和解答。 第一部分&…

【qt信号槽-5】信号槽相关注意事项记录

背景&#xff1a; 信号槽是qt很重要的概念&#xff0c;遇到问题帮助没少看。其中就有signals and slots这一章节&#xff0c;说得很到位。 概念琐碎&#xff0c;记录备忘。不对之处望指正。 【qt信号槽-1】槽函数重写问题&#xff0c;qt_metacall和qt_static_metacall-CSDN博…

动力电池系统介绍(十四)——热管理系统

动力电池系统介绍&#xff08;十四&#xff09; 一、梗概二、座舱热管理&#xff08;汽车空调&#xff09;2.1 空调制冷2.2 空调制热2.2.1 传统燃油汽车空调制热2.2.2 新能源汽车空调制热 三、动力系统热管理3.1 燃油车发动机热管理3.1.1 冷却系统3.1.2 润滑系统3.1.3 进排气系…

【QT】Model/View结构

目录 1 概述 2 Mode/View基本原理 3 数据模型 4 视图组件 5 代理 6 Model/View结构的一些概念 6.1 Model/View的基本结构 6.2 模型索引 6.3 行号和列号 6.4 父项 6.5 项的角色 1 概述 Model/View&#xff08;模型/视图&#xff09;结构是Qt中用界面组件显示与编辑数据的一种结构…

算法基础之筛质数

筛质数 核心思想&#xff1a;筛法求质数 埃氏筛法: 每次用 2 3 4…. p-1 筛 2 - p之间的数出现2 3 4 …的倍数时 去掉(4实际已经被去掉 不会用4去筛)当2~p-1的数都没有筛掉p 说明p是质数 优化: 只用2~p-1中质数筛 线性筛法: 核心: n只会被其最小质因子筛掉 每一个合数都只…

MFC 消息映射机制

目录 消息映射机制概述 宏展开 宏展开的作用 消息映射机制的执行流程 消息处理 消息映射机制概述 MFC的消息映射映射机制是可以在不重写WindowProc虚函数的大前提下&#xff0c;仍然可以处理消息。 类必须具备的要件 类内必须添加声明宏 DECLARE_MESSAGE_MAP() 类外…

linux 应用开发笔记---【线程】

1.概念&#xff1a; 线程是参与系统调度的最小单位&#xff0c;它被包含在进程中&#xff0c;是进程的实际运行单位 一个进程可以创建多个线程&#xff0c;多个线程并发运行&#xff0c;每个线程执行不同的任务 2.如何创建线程 当一个程序启动的时候&#xff0c;一个进程被…

Cesium 3DTiles数据格式详解

目录 0 引言1 3DTiles1.1 起源1.2 后缀类型及特点1.2.1 b3dm1.2.2 i3dm1.2.3 pnts1.2.4 cmpt1.2.5 json1.2.6 总结 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;CesiumforUnreal专栏&#x1f4a5; 标题&#xff1a;Cesium 3DTiles数据格式详解❣…

【Netty】Netty核心API及使用

目录 Netty核心APIChannelHandler及其实现类ChannelPipelineChannelHandlerContextChannelOptionChannelFutureEventLoopGroup和实现类NioEventLoopGroupServerBootstrap和BootstrapUnpooled类 Netty入门案例引入依赖Netty服务端编写Netty客户端编写 Netty核心API ChannelHand…

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

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

FPGA模块——以太网芯片MDIO读写

FPGA模块——以太网MDIO读写 MDIO接口介绍MDIO接口代码&#xff08;1&#xff09;MDIO接口驱动代码&#xff08;2&#xff09;使用MDIO驱动的代码 MDIO接口介绍 MDIO是串行管理接口。MAC 和 PHY 芯片有一个配置接口&#xff0c;即 MDIO 接口&#xff0c;可以配置 PHY 芯片的工…

读书笔记产品经理学习笔记1-忘掉技术,先看客户需求

技术到产品思维的转换 以前做技术的时候&#xff0c;扮演的角色是怎样多快好省的完成开发。现在做产品了&#xff0c;你得自己定产品方案&#xff0c;让别人来开发。最重要的是先弄清楚客户的需求是什么&#xff0c;要解决什么问题&#xff0c;再看产品怎么设计&#xff0c;然…

你想改win11系统中窗口、菜单等的字体? 微软不想让你改

如果你感觉win11系统中显示的字体不好看&#xff0c;想换。等一等&#xff0c;微软本不想让你改。 Windows 11 在默认情况下并没有提供直接修改系统默认字体的选项&#xff0c;而需要进行注册表或其他高级设置来更改系统字体。这可能是因为微软希望保持系统的一致性和稳定性&a…

[Realtek sdk-3.4.14b]RTL8197FH-VG+RTL8812F WiFi使用功率限制功能使用说明

sdk说明 ** Gateway/AP firmware v3.4.14b – Aug 26, 2019**  Wireless LAN driver changes as:  Refine WiFi Stability and Performance  Add 8812F MU-MIMO  Add 97G/8812F multiple mac-clone  Add 97G 2T3R antenna diversity  Fix 97G/8812F/8814B MP issu…

可狱可囚的爬虫系列课程 07:BeautifulSoup4(bs4)库的使用

前面一直在讲 Requests 模块如何使用&#xff0c;那都是在请求阶段要做的事情&#xff0c;相信很多网友都在等一个能够开始爬网站信息的教程&#xff0c;今天它来了&#xff0c;今天我要给大家讲一个很简单易懂的库&#xff1a;BeautifulSoup4。 一、概述&安装 Beautiful…