Netty之编解码器框架
Netty之编解码器框架
- 什么是编解码器
- 解码器
- ByteToMessageDecoder
- ReplayingDecoder
- MessageToMessageDecoder
- TooLongFrameException
- 编码器
- MessageToByteEncoder
- MessageToMessageEncoder
- 抽象的编解码器类
- ByteToMessageCodec
- MessageToMessageCodec
- CombinedChannelDuplexHandler
什么是编解码器
每个网络应用程序都必须定义如何解析在两个节点之间来回传输的原始字节,以及如何将其和目标应用程序的数据格式做相互转换。这种转换逻辑由编解码器处理,编解码器由编码器(Encoder)和解码器(Decoder)组成,它们每种都可以将字节流从一种格式转换为另一种格式。
我们常用的编解码器是:
- MessageToByteEncoder:将数据从本身的格式转换为字节流。出站的时候用。
- ByteToMessageDecoder:将字节流转换为它原来的格式。入站的的时候用。
解码器
- 将字节解码为消息 —— ByteToMessageDecoder
- 将一种消息类型解码为另一种 —— MessageToMessageDecoder
因为解码器是负责将入站数据从一种格式转换到另一种格式的,所以Netty 的解码器实现了ChannelInboundHandler。
什么时候会用到解码器呢?很简单:每当需要为ChannelPipeline 中的下一个ChannelInboundHandler 转换入站数据时会用到。此外,得益于ChannelPipeline 的设计,可以将多个解码器链接在一起,以实现任意复杂的转换逻辑。
ByteToMessageDecoder
将字节解码为消息(或者另一个字节序列)是一项如此常见的任务,以至于Netty 为它提供了一个抽象的基类:ByteToMessageDecoder。由于你不可能知道远程节点是否会一次性地发送一个完整的消息,所以这个类会对入站数据进行缓冲,直到它准备好处理。
示例:
将字节流(存储在ByteBuf中)解码为 int 流(这里是自动装箱为Integer存储在List中)。
注意:
一旦消息被编码或解码,它就会被ReferenceCountUtil.release(message) 调用自动释放。如果想要保留引用稍后使用,可以调用ReferenceCountUtil.retain(message)
ReplayingDecoder
看了前面的ByteToMessageDecoder示例代码,我们会觉得每次判断in.readableBytes()十分不优雅。ReplayingDecoder可以让我们不必调用readableBytes()方法。它有一个自定义的ByteBuf实现——ReplayingDecoderBytebuf,其将在内部执行readableBytes()。
示例:
- 如果没有足够的字节可处理了,readInt() 方法的实现将抛出一个异常(实际上是一个 Signal),其将在基类中被捕获并处理。
- 如果有更多的字节可处理,decode() 会被再次调用。
注意:
- 并不是所有的ByteBuf操作都被支持。
- ReplayingDecoder稍慢于ByteToMessageDecoder。
总而言之:如果使用 ByteToMessageDecoder 觉得不会很复杂,就使用 ByteToMessageDecoder 。否则,使用ReplayingDecoder。
MessageToMessageDecoder
示例:
将 Integer 转换为 String 。
TooLongFrameException
由于Netty 是一个异步框架,所以需要在字节可以解码之前在内存中缓冲它们。因此,不能让解码器缓冲大量的数据以至于耗尽可用的内存。为了解除这个常见的顾虑,Netty 提供了TooLongFrameException 类,其将由解码器在帧超出指定的大小限制时抛出。
为了避免这种情况,你可以设置一个最大字节数的阈值,如果超出该阈值,则会导致抛出一个TooLongFrameException(随后会被ChannelHandler.exceptionCaught()方法捕获)。然后,如何处理该异常则完全取决于该解码器的用户。某些协议(如HTTP)可能允许你返回一个特殊的响应。而在其他的情况下,唯一的选择可能就是关闭对应的连接。
示例:
编码器
- 将消息编码为字节——MessageToByteEncoder
- 将消息编码为消息——MessageToMessageEncoder
MessageToByteEncoder
示例:
MessageToMessageEncoder
示例:
抽象的编解码器类
我们一直将解码器和编码器作为单独的实体讨论,但是你有时将会发现在同一个类中管理入站和出站数据和消息的转换是很有用的。Netty 的抽象编解码器类正好用于这个目的,因为它们每个都将捆绑一个解码器/编码器对,以处理我们一直在学习的这两种类型的操作。这些类同时实现了ChannelInboundHandler 和ChannelOutboundHandler 接口。
为什么我们并没有一直优先于单独的解码器和编码器使用这些复合类呢?因为通过尽可能地将这两种功能分开,最大化了代码的可重用性和可扩展性,这是Netty 设计的一个基本原则。
ByteToMessageCodec
结合了 ByteToMessageDecoder 和 MessageToByteEncoder 。
MessageToMessageCodec
CombinedChannelDuplexHandler
不像 ByteToMessageCodec 和 MessageToMessageCodec 继承的 ChannelDuplexHandler 那样,继承 ChannelInboundHandlerAdapter 又实现 ChannelOutboundHandler,而是充当 ChannelInboundHandler 和 ChannelOutboundHandler 的容器。这样既避免了结合一个解码器和编码器对可重用性造成的影响,又能拥有将解码器和编码器作为一个单独的单元来部署的便利性。
示例:
解码器:
编码器:
编解码器:
个人认为这个类除了能让你的 ChannelInitializer 更加简洁,确实没什么用。
参考自:《Netty实战》
Netty之编解码器框架相关推荐
- netty的编解码器理解(转)
一.简介 在网络应用中需要实现某种编解码器,将原始字节数据与自定义的消息对象进行互相转换.网络中都是以字节码的数据形式来传输数据的,服务器编码数据后发送到客户端,客户端需要对数据进行解码. 编解码器由 ...
- netty(4)--编解码器
netty(4)–编解码器 每个网络应用程序都必须定义如何解析在两个节点之间来回传输的原始字节,以及如何将其和目标应用程序的数据格式做相互转换.这种转换逻辑由编解码器处理,编解码器由编码器和解码器 ...
- Netty和RPC框架线程模型分析
<Netty 进阶之路>.<分布式服务框架原理与实践>作者李林锋深入剖析Netty和RPC框架线程模型.李林锋已在 InfoQ 上开设 Netty 专题持续出稿,感兴趣的同学可 ...
- Netty 和 RPC 框架线程模型分析
https://www.infoq.cn/article/9Ib3hbKSgQaALj02-90y 1. 背景 1.1 线程模型的重要性 对于 RPC 框架而言,影响其性能指标的主要有三个要素: I/ ...
- Netty的编解码器
Netty常用编解码器 Netty 常用编码器 MessageToByteEncoder 对象编码成字节流 MessageToMessageEncoder 一种消息类型编码成另外一种消息类型 Nett ...
- Netty系列之Netty编解码框架分析
1. 背景 1.1. 编解码技术 通常我们也习惯将编码(Encode)称为序列化(serialization),它将对象序列化为字节数组,用于网络传输.数据持久化或者其它用途. 反之,解码(Decod ...
- 基于Netty的RPC框架
概述 RPC(Remote Procedure Call),远程过程调用,是一个计算机通信协议,该协议允许运行一个进程调用另一个进程,而程序员无需额外为这个交互作用编程. 两个或者多个应用程序分布在不 ...
- Java编写基于netty的RPC框架
一 简单概念RPC: ( Remote Procedure Call),远程调用过程,是通过网络调用远程计算机的进程中某个方法,从而获取到想要的数据,过程如同调用本地的方法一样.阻塞IO :当阻塞I/ ...
- 手动实现一个基于netty的RPC框架(模拟dubble)
轻量级RPC框架开发 内容安排: 1.掌握RPC原理 2.掌握nio操作 3.掌握netty简单的api 4.掌握自定义RPC框架 RPC原理学习 什么是RPC RPC(Remote Procedur ...
- 网络编程之Netty(网络通信框架)的基础篇
网络编程 Netty的介绍及应用场景 Netty的介绍 Netty的应用场景 I/O模型 I/O模型基本说明 BIO.NIO.AIO适用场景分析 Java BIO Java BIO基本介绍 Java ...
最新文章
- Java中四种线程池介绍
- UnicodeEncodeError: 'UCS-2' codec can't encode characters in position 8-8: Non-BMP character not sup
- 区块链共识算法Proof-of-Stake (PoS/权益证明) 常见问题解答 (1)
- 我今天对JavaFX的了解
- [css] 使用css3实现一个斑马线的效果
- 初中学历做开发,3年在北京买了房,超过了99%的程序员!
- 在 CentOS 上安装和配置 Xen 虚拟化
- “你的深度学习框架包含15个漏洞”,360说 | 附论文
- 设计模式_01单例模式
- 一种巧妙且简单的数据增强方法 - MixUp 小综述
- 各位学Python的要小心了!!!
- html5编写商城页面,HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第2章HTML基础知识...
- Pandas处理缺失数据
- PhotoshopCS4的抽出滤镜下载及安装方法
- imo CEO乔月猛:我们是史上研发投入最大的创业团队
- 摸索着的坚持!!!!2015年9月29日13:14
- 运维日常之机房浪潮服务器硬盘红灯亮起,服务器一直响,raid磁盘红色。。。故障解决方法
- Android The emulator process for AVD XXX has terminated.
- matlab 数组索引必须为正整数或逻辑值
- 疯狂砸钱营销,大力推广新品,香飘飘为啥还是留不住消费者?