Netty入门(六)Decoder(解码器)
2018-06-18 01:11:10来源:未知 阅读 ()
Netty 提供了丰富的解码器抽象基类,主要分为两类:
- 解码字节到消息(ByteToMessageDecoder 和 ReplayingDecoder)
- 解码消息到消息(MessageToMessageDecoder)
一、ByteToMessageDecoder
ByteToMessageDecoder 用于将字节转为信息(或其他字节序列)。方法如下:
在下面的例子中,我们将实现从入站 ByteBuf 读取每个整数并将其传递给 pipeline 中的下一个 ChannalInboundHandler。流程如下:
代码如下:
1 /** 2 * 读取四字节,解码成整形 3 * 继承于 ByteToMessageDecoder 4 * 5 */ 6 public class ToIntegerDecoder extends ByteToMessageDecoder { 7 8 @Override 9 protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { 10 if(in.readableBytes() >= 4) { // int是4字节 11 out.add(in.readInt()); // 添加到解码信息的List中 12 } 13 } 14 15 }
注意,一旦一个消息被编码或解码会自动调用 ReferenceCountUtil.release(message)。如果你稍后还需要用到这个引用,你可以调用 ReferenceCountUtil.retain(message)。
二、ReplayingDecoder
上面的例子读取缓冲区的数据之前需要检查缓冲区是否有足够的字节,使用 ReplayingDecoder 就无需自己检查。若 ByteBuf 中有足够的字节,则会正常读取;若没有足够的字节则会停止解码。如下:
1 /** 2 * 读取四字节,解码成整形 3 * 继承于ReplayingDecoder,不需要检查缓存区是否有足够的字节 4 * 5 */ 6 public class ToIntegerDecoder2 extends ReplayingDecoder<Void> { 7 8 @Override 9 protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { 10 out.add(in.readInt()); // 读取整形并添加到解码信息的List中 11 } 12 13 }
三、MessageToMessageDecoder
用于从一种消息解码为另一种消息(例如,POJO 到 POJO)。与上面类似,代码如下:
1 /** 2 * 将整形解码为字符串 3 * 继承于MessageToMessageDecoder 4 * 5 */ 6 public class IntegerToStringDecoder extends MessageToMessageDecoder<Integer> { 7 8 @Override 9 protected void decode(ChannelHandlerContext ctx, Integer msg, List<Object> out) throws Exception { 10 out.add(String.valueOf(msg)); // 将整形转换为字符串 11 } 12 13 }
四、在解码中处理太大的帧
Netty 是异步架构需要将缓冲区字节存在内存中,知道你能够解码它们。因此,你不能让你的解码器缓存太多的数据以免耗尽可用内存。下面为解决方案:
1 /** 2 * 在解码时处理太大的帧 3 * 4 */ 5 public class SafeByteToMessageDecoder extends ByteToMessageDecoder { 6 private static final int MAX_FRAME_SIZE = 1024; 7 8 @Override 9 protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { 10 int readable = in.readableBytes(); 11 if(readable > MAX_FRAME_SIZE) { // 缓冲区数据过大 12 in.skipBytes(readable); // 忽略所有可读的字节 13 // 抛出异常通知这个帧数据超长 14 throw new TooLongFrameException("帧数据超长"); 15 } 16 // TODO 数据编码 17 } 18 19 }
这种保护很重要,尤其是当你编码一个有可变帧大小的协议的时候。
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- logstash系列-入门整理 2020-06-10
- Java 入门教程 2020-06-09
- 这可能是目前最透彻的Netty讲解了... 2020-06-08
- RocketMQ4.4 入门进阶+实战 2020-06-08
- 因为 MongoDB 没入门,我丢了一份实习工作 2020-06-07
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash