首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >netty系列之:netty中常用的字符串编码解码器

netty系列之:netty中常用的字符串编码解码器

作者头像
程序那些事
发布于 2022-05-17 00:58:00
发布于 2022-05-17 00:58:00
62600
代码可运行
举报
文章被收录于专栏:程序那些事程序那些事
运行总次数:0
代码可运行

简介

字符串是我们程序中最常用到的消息格式,也是最简单的消息格式,但是正因为字符串string太过简单,不能附加更多的信息,所以在netty中选择的是使用byteBuf作为最底层的消息传递载体。

虽然底层使用的ByteBuf,但是对于程序员来说,还是希望能够使用这种最简单的字符串格式,那么有什么简单的方法吗?

netty中的字符串编码解码器

为了解决在netty的channel中传递字符串的问题,netty提供了针对于字符串的编码和解码器,分别是StringEncoder和StringDecoder。

我们来看下他们是怎么在程序中使用的,首先是将StringDecoder和StringEncoder加入channelPipeline中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   ChannelPipeline pipeline = ...;

   // Decoders
   pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(80));
   pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));

   // Encoder
   pipeline.addLast("stringEncoder", new StringEncoder(CharsetUtil.UTF_8));

注意,这里我们在使用StringDecoder之前还调用了LineBasedFrameDecoder,先把数据按行进行分割,然后再进行字符串的读取。

那么有人要问了,decoder加入了LineBasedFrameDecoder预处理,为什么写入的时候没有添加行的分割符呢?

事实上这里有两种处理方式,第一种就是在向channel中写入字符串的时候,手动加上行分隔符,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   void channelRead(ChannelHandlerContext ctx, String msg) {
       ch.write("Did you say '" + msg + "'?\n");
   }

如果不想每次都在msg后面加上换行符,那么可以将StringEncoder替换成为LineEncoder,上面的pipeline就变成下面这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   ChannelPipeline pipeline = ...;

   // Decoders
   pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(80));
   pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));

   // Encoder
   pipeline.addLast("lineEncoder", new LineEncoder(LineSeparator.UNIX, CharsetUtil.UTF_8));

这样,我们在handler中就不需要手动添加换行符了,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   void channelRead(ChannelHandlerContext ctx, String msg) {
       ch.write("Did you say '" + msg + "'?");
   }

不同平台的换行符

在unix和windows平台传递过文本文件的朋友可能会遇到一个问题,就是windows创建的文本文件,如果在unix下面打开的话,会发现每行后面多出了一个特殊字符,这是因为unix和windows平台定义的换行符是不同的。

在unix平台通常使用”\n”来换行,而在windows平台则使用””\r\n”来换行。

java程序因为是跨平台的,写出的程序可能运行在unix平台,也可能运行在windows平台,所以我们需要有一个办法来获取平台的换行符,netty提供了一个LineSeparator的类来完成这个工作。

LineSeparator中有三个换行符的定义,分别是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   public static final LineSeparator DEFAULT = new LineSeparator(StringUtil.NEWLINE);

    public static final LineSeparator UNIX = new LineSeparator("\n");

    public static final LineSeparator WINDOWS = new LineSeparator("\r\n");

UNIX和WINDOWS很好理解,他们就是我们刚刚讲到的不同的平台。

那么什么是DEFAULT呢?DEFAULT中传入的NEWLINE,实际上是从系统属性中获取到的,如果没有获取到,则使用默认的”\n”。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static final String NEWLINE = SystemPropertyUtil.get("line.separator", "\n");

字符串编码的实现

上面我们讲到了和字符串编码解码相关的类分别是StringEncoder,LineEncoder和StringDecoder,我们来详细看下这三个类的实现。

首先是StringEncoder,StringEncoder继承了MessageToMessageEncoder:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class StringEncoder extends MessageToMessageEncoder<CharSequence>

泛型中的CharSequence表示StringEncoder要encode的对象是CharSequence,也就是字符序列。

虽然大家常用String这个类,但是不一定大家都知道String其实是CharSequence的子类,所以StringEncoder也可以编码字符串。

StringEncoder的编码逻辑很简单,将传入的字符串msg转换成为CharBuffer,然后调用ByteBufUtil的encodeString方法就可以转换成为ByteBuf,并加入out中去:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    protected void encode(ChannelHandlerContext ctx, CharSequence msg, List<Object> out) throws Exception {
        if (msg.length() == 0) {
            return;
        }
        out.add(ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(msg), charset));
    }

LineEncoder和StringEncoder很类似,它也是继承自MessageToMessageEncoder:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class LineEncoder extends MessageToMessageEncoder<CharSequence>

不同之处在于encoder方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    protected void encode(ChannelHandlerContext ctx, CharSequence msg, List<Object> out) throws Exception {
        ByteBuf buffer = ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(msg), charset, lineSeparator.length);
        buffer.writeBytes(lineSeparator);
        out.add(buffer);
    }

ByteBufUtil的encodeString多了一个lineSeparator.length参数,用来预留lineSeparator的位置,然后在返回的ByteBuf后面加上lineSeparator作为最终的输出。

StringDecoder是和StringEncoder相反的过程:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class StringDecoder extends MessageToMessageDecoder<ByteBuf>

这里的ByteBuf表示的是要解码的对象是ByteBuf,我们看下他的解码方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        out.add(msg.toString(charset));
    }

直接调用msg.toString方法即可将ByteBuf转换成为字符串。

总结

以上就是netty中对字符串的编码解码器,通过使用这几个编码解码器可以大大简化我们的工作。

本文已收录于 http://www.flydean.com/14-6-netty-codec-string/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序那些事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Netty Review - StringEncoder字符串编码器和StringDecoder 解码器的使用与源码解读
Netty是一个高性能的网络应用程序框架,它提供了丰富的功能,包括编解码器,这些编解码器用于在网络中发送和接收数据时进行数据的编码和解码。
小小工匠
2023/12/22
1K0
Netty Review - StringEncoder字符串编码器和StringDecoder 解码器的使用与源码解读
netty系列之:文本聊天室
经过之前的系列文章,我们已经知道了netty的运行原理,还介绍了基本的netty服务搭建流程和消息处理器的写法。今天本文会给大家介绍一个更加复杂的例子,文本聊天室。
程序那些事
2021/08/13
3870
通信密码学:探秘Netty中解码器的神奇力量
在网络通信的秘境中,解码器就如同一扇通向数据真相的大门,能够解读二进制流中的信息。在这篇文章中,我们将一同踏入Netty的通信迷宫,深入研究常用的解码器,看看它们如何帮助我们读懂通信的密码。
一只牛博
2025/05/30
1180
通信密码学:探秘Netty中解码器的神奇力量
高性能NIO框架Netty-对象传输
上篇文章高性能NIO框架Netty入门篇我们对Netty做了一个简单的介绍,并且写了一个入门的Demo,客户端往服务端发送一个字符串的消息,服务端回复一个字符串的消息,今天我们来学习下在Netty中怎么使用对象来传输数据。 上篇文章中传输字符串我们用的是框架自带的StringEncoder,StringDecoder编解码器,现在想要通过对象来传输数据,该怎么弄呢? 既然StringEncoder和StringDecoder可以传输字符串,我们来看看这2个类的源码不就知道它们到底做了一些什么工作。 Stri
猿天地
2018/04/03
8330
netty系列之:netty中的懒人编码解码器
netty之所以强大,是因为它内置了很多非常有用的编码解码器,通过使用这些编码解码器可以很方便的搭建出非常强大的应用程序,今天给大家讲讲netty中最基本的内置编码解码器。
程序那些事
2021/08/20
9520
netty通信框架(socket通信详解)
  题外话,很多人都把JDK1.4提供的NIO称之为异步非阻塞I/O;其实,并不然,从严格意义上面讲,它只能称为非阻塞I/O。在JDK1.7提供的NIO 2.0,新增了异步的套接字通道Channel,它才是真正的异步非阻塞I/O。下表是不同I/O模型的对比:
全栈程序员站长
2022/08/01
2.2K0
netty系列之:netty中的核心编码器bytes数组
我们知道netty中数据传输的核心是ByteBuf,ByteBuf提供了多种数据读写的方法,包括基本类型和byte数组的读写方法。如果要在netty中传输这些数据,那么需要构建ByteBuf,然后调用ByteBuf中对应的方法写入对应的数据,接着套用netty中标准的模板即可使用。
程序那些事
2022/04/25
7310
netty系列之:netty中的核心编码器bytes数组
Netty一文深入
通过2个位置指针来协助缓冲区的读写,读使用 readerIndex,写使用 writerIndex。
趣学程序-shaofeer
2020/07/17
8270
Netty一文深入
Netty ChannelHandler与ChannelPipeline源码解读
  ChannelHandler基本上是我们第一次接触Netty就会碰到的对象,我们自定义的各种ChannelHandler主要用于处理我们系统的各种业务逻辑,比如发生了active事件后的处理逻辑,发生了读事件的处理逻辑,下面先来看一下ChannelHandler的类继承图:
良辰美景TT
2018/09/11
5600
Netty ChannelHandler与ChannelPipeline源码解读
netty案例,netty4.1基础入门篇五《NettyServer字符串编码器》
netty通信就像一个流水channel管道,我们可以在管道的中间插入一些‘挡板’为我们服务。比如字符串的编码解码,在前面我们使用new StringDecoder(Charset.forName("GBK"))进行字符串解码,这样我们在收取数据就不需要手动处理字节码。那么本章节我们使用与之对应的new StringEncoder(Charset.forName("GBK"))进行进行字符串编码,用以实现服务端在发送数据的时候只需要传输字符串内容即可。
小傅哥
2020/07/14
8240
netty案例,netty4.1基础入门篇五《NettyServer字符串编码器》
netty系列之:自定义编码解码器
在之前的netty系列文章中,我们讲到了如何将对象或者String转换成为ByteBuf,通过使用netty自带的encoder和decoder可以实现非常方便的对象和ByteBuf之间的转换,然后就可以向channel中随意写入对象和字符串了。
程序那些事
2021/08/16
7700
netty系列之:netty中的核心编码器base64
我们知道数据在netty中传输是以ByteBuf的形式进行的,可以说ByteBuf是netty的数据传输基础。但是对于现代的应用程序来说,通常我们需要用到其他的数据结构或者类型。
程序那些事
2022/04/22
6130
一个低级错误引发Netty编码解码中文异常
最近在调研Netty的使用,在编写编码解码模块的时候遇到了一个中文字符串编码和解码异常的情况,后来发现是笔者犯了个低级错误。这里做一个小小的回顾。
Throwable
2020/06/23
2.3K0
一个低级错误引发Netty编码解码中文异常
netty案例,netty4.1基础入门篇五《NettyServer字符串编码器》
netty通信就向一个流水channel管道,我们可以在管道的中间插入一些‘挡板’为我们服务。比如字符串的编码解码,在前面我们使用new StringDecoder(Charset.forName("GBK"))进行字符串解码,这样我们在收取数据就不需要手动处理字节码。那么本章节我们使用与之对应的new StringEncoder(Charset.forName("GBK"))进行进行字符串编码,用以实现服务端在发送数据的时候只需要传输字符串内容即可。
小傅哥
2020/01/20
4720
netty案例,netty4.1基础入门篇五《NettyServer字符串编码器》
java架构之路-(netty专题)netty的编解码(出入战)与粘包拆包
  上次博客我们主要说了netty的基本使用,都是一些固定的模式去写的,我们只需要关注我们的拦截器怎么去写就可以了,然后我们用我们的基础示例,改造了一个简单的聊天室程序,可以看到内部加了一个StringEncoder和StringDecoder,这个就是用来编解码我们字符串的,这次我们就来说说这个编解码。
小菜的不能再菜
2020/02/24
7460
Kotlin + Netty 在 Android 上实现 Socket 的服务端
最近的一个项目:需要使用 Android App 作为 Socket 的服务端,并且一个端口能够同时监听 TCP/Web Socket 协议。
fengzhizi715
2019/08/12
3.9K0
Netty的常用编解码器与使用
我们本章节将了解基本的编解码器以及自定义编解码器的使用,在了解之前,我们先看一段代码:
止术
2021/08/06
8590
Netty的常用编解码器与使用
【Netty】01-服务端和客户端的搭建
Netty服务端和客户端的搭建 为什么采用Netty,而不采用Nio 使用Netty创建服务器端 使用Netty创建客户端 为什么采用Netty,而不采用Nio Nio原生Api很复杂 Nio存在epoll bug,会产生空轮询,导致cpu被占用100% Netty是基于Nio进行包装,性能上会更高 Netty学习成本和使用成本更低 摘抄自其他文章, Netty的优点总结: 通过对Netty的分析,我们将它的优点总结如下。 ◎ API使用简单,开发门槛低; ◎ 功能强大,预置了多种编解码功能,支
envoke
2020/09/17
1.1K0
netty
BIO 同步阻塞bio:链接数目较少 public static void main(String args[]) throws IOException { ExecutorService p
Dean0731
2020/10/10
5520
netty
Netty 是如何解决 TCP 粘包拆包的?
那么数据在通信层传播其实就像河水一样并没有明显的分界线,而数据具体表示什么意思什么地方有句号什么地方有分号这个对于TCP底层来说并不清楚。应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段,之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。
Java技术栈
2021/07/16
8660
Netty 是如何解决 TCP 粘包拆包的?
相关推荐
Netty Review - StringEncoder字符串编码器和StringDecoder 解码器的使用与源码解读
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档