一、解码和编码的作用
- netty从底层java通道读到ByteBuf二进制数据,传入Netty通道的流水线。随后开始入站处理。
- 在入站处理的过程中,需要将ByteBuf二进制数据解码成POJO对象。这个解码过程,通过Netty的Decoder解码器实现。
- 在出站处理过程中,业务处理后的结果,需要从POJO编码为最终的ByteBuf二进制数据,然后通过底层java通道发送到对端。这个编码过程,通过Netty的Encoder解码器实现。
二、Decoder原理与实践
一个标准的解码器将输入类型为ByteBuf缓冲区的数据进行解码,输出一个一个的Java POJO对象。Netty内置了这个解码器,叫作ByteToMessageDecoder,位在Netty的io.netty.handler.codec包中。
- 作为解码器的父类,ByteToMessageDecoder仅仅提供了一个流程性质的框架:它仅仅将子类的decode方法解码之后的Object结果,放入自己内部的结果列表List<Object>中,最终,父类会负责将List<Object>中的元素,一个一个地传递给下一个站。
- 如果要实现一个自己的解码器,首先继承ByteToMessageDecoder抽象类。然后,实现其基类的decode抽象方法。将解码的逻辑,写入此方法。
- ReplayingDecoder类是ByteToMessageDecoder的子类。其作用是:
· 在读取ByteBuf缓冲区的数据之前,需要检查缓冲区是否有足够的字节。
· 若ByteBuf中有足够的字节,则会正常读取;反之,如果没有足够的字节,则会停止解码。
三、整数分包解码案例
在Java的NIO中,由于NIO的非阻塞性,就会出现图中这样的问题。怎样保证一次性读取到完整的数据,就成了一个大问题。
答:如果发现当前ByteBuf中所有可读数据不够,需要结束解析,直到可读数据是足够的。
解码整数序列-解码两个整数,并求和作为解码结果
相当于设置一个游戏存档
父类中有两个重要的变量:
private S state;
private int checkpoint;//保存当前读取位置//相当于一个游戏存档
//...
public class IntegerAddDecoder extends ReplayingDecoder<IntegerAddDecoder.Status>
{
enum Status {
PARSE_1,
PARSE_2
}
private int first;
private int second;
public IntegerAddDecoder() {
//在构造函数中,需要初始化父类的state属性,表示当前阶段
super(Status.PARSE_1);
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception
{
switch (state())