【Netty报错:】XXXDecoder.decode() did not read anything but decoded a message.

Netty解码器报错:XXXDecoder.decode() did not read anything but decoded a message.

从字面意思来看,就是说没有读取任何数据,但是却解析出来了一个对象。
【Netty报错:】XXXDecoder.decode() did not read anything but decoded a message.

1、问题引出

在写自定义的基于String的解码器的时候,在使用该解码器进行解码的时候会抛出这个异常。

  • 对应的解码器代码很简单,就是将ByteBuf转化为一个字符串,然后添加到list中,供后面的handler进行处理。
    【Netty报错:】XXXDecoder.decode() did not read anything but decoded a message.
  • 编码器代码也很简单,就是将字符串变成一个byte数组,写到ByteBuf中,供后面的handler进行处理。
    【Netty报错:】XXXDecoder.decode() did not read anything but decoded a message.

2、ByteToMessageDecoder源码解析

当有数据到来的时候,会调用handler的channelRead方法,代码逻辑很简单大概分为三步:

  • 读取字节流,累加字节流
  • 将读取到的字节流交由子类的decoder方法解析,也就是我们自定义的解码器
  • 将解析出来的对象继续向下传播
    【Netty报错:】XXXDecoder.decode() did not read anything but decoded a message.
    其中在调用子类decoder方法的时候,会有这么一段判断逻辑:
    【Netty报错:】XXXDecoder.decode() did not read anything but decoded a message.
  • 记录一下在解析之前list里面的对象数量。
  • 记录一下解析之前字节流里面可读的字节数。
  • 然后调用子类的解析方法
  • 调用之后,list里面的对象和之前的相等,说明没有解析出对象,此时分两种情况,一种没有读取到数据,另一种解析出部分数据但不够构成一个对象
  • 最后就来到异常抛出的地方,也就是解析出来了对象,但是bytebuf可读的字节容量和解析之前可读的字节数是相等的,换句话说就是明明解析出来了对象,但是没有读取走数据,因此这里会抛出异常。

那么为什么会进这个if呢?看自定义的解码器,只是单纯的将byteBuf转换成了一个String,byteBuf的readIndex并没有任何移动,因此byteBuf可读的字节数量在解析前后是相等的。

3、问题解决

知道了异常抛出的原因,这下解决它还是很简单的,只需要让byteBuf的readindex索引随读取的数据向前移动即可,因此可以有两种解决方式:

  • 将buteBuf里面的数据读取到放在一个byte数组中,然后,将byte数组转化为String向下传播,这样byteBuf的readIndex会向前移动的。
    【Netty报错:】XXXDecoder.decode() did not read anything but decoded a message.
  • 继续采用之前的方式,但是读取完之后,人为让readindex向前移动:
  • 【Netty报错:】XXXDecoder.decode() did not read anything but decoded a message.
    采用这两种方式,均可以完美解决问题。
上一篇:typeof 和 instanceof


下一篇:C# MySql批量导入 忽略自增主键