翻译过来就是说:什么也没读,只是解码了一条信息
编码器是如下图

public class ByteToIntegerDecoder extends ByteToMessageDecoder {@Overridepublic void decode(ChannelHandlerContext ctx, ByteBuf in,List<Object> out) throws Exception {//ByteBuf byteBuf = in.retainedDuplicate();ByteBuf byteBuf=in;int readerIndex = byteBuf.readerIndex();int i = byteBuf.readableBytes();if (i >= 4) {  // Check if there are at least 4 bytes readableString str;if(byteBuf.hasArray()) { // 处理堆缓冲区str = new String(byteBuf.array(), byteBuf.arrayOffset() + byteBuf.readerIndex(), byteBuf.readableBytes());} else { // 处理直接缓冲区以及复合缓冲区byte[] bytes = new byte[in.readableBytes()];byteBuf.getBytes(readerIndex, bytes);str = new String(bytes, 0, byteBuf.readableBytes());}System.err.println("ByteToIntegerDecoder decode msg is " + str);out.add(str);      //Read integer from inbound ByteBuf, add to the List of decodec messages}}
}

我传过来是个String字符串,当做对象来解码

系统显示打印出了我发过来的字符串,然后又执行了一遍就报错了。

nett资料上如下图:

大概意思就是说,这个ByteBuf还是是netty的那个传数据流的容器,这个List 是最终要返回给下面handler用的东西

传数据时这个decode方法会一直被调用,直到ByteBuf里面没有可以读取的数据,并且List也不是null就会传给下面的handler了。

那重点就是这俩:1.直到ByteBuf里面没有可以读取的数据  2.并且List也不是null

符合这俩条件,decode就会把数据交给handler。

2.问题我好理解,我out.add了,List已经不是null了。

1.问题就是怎么知道ByteBuf里有没有数据了?

那得看ByteBuf咋工作了:

代码里,先bytebuf读取一下里面可以读取的字节容量,然后判断了是否大于4,如果大于4就表示我可以进行解析然后往List里添加了数据了。

然后通过String的构造方法把byte数组转换成String字符串,起始是0,截止是Bytebuf里放的流数据长度。

通过打断点发现,这个方法会在数据刚进入解码是调用一次,读取到可读长度,赋值给oldInputLength;之后会在最后结束此次解码时候再进去一次,if (outSize == out.size()) 这就是判断有没往out里加入数据,初始 outSize = 0;if (oldInputLength == in.readableBytes()) 这个是判断你有没有去把ByteBuf in里的东西给读出来。如果还是和之前赋值的oldInputLength一样的大小,那就表明没有读取过。这样就会抛出以上的异常。

protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {try {while(true) {if (in.isReadable()) {int outSize = out.size();if (outSize > 0) {fireChannelRead(ctx, out, outSize);out.clear();if (ctx.isRemoved()) {return;}outSize = 0;}int oldInputLength = in.readableBytes();this.decodeRemovalReentryProtection(ctx, in, out);if (!ctx.isRemoved()) {if (outSize == out.size()) {if (oldInputLength != in.readableBytes()) {continue;}} else {if (oldInputLength == in.readableBytes()) {throw new DecoderException(StringUtil.simpleClassName(this.getClass()) + ".decode() did not read anything but decoded a message.");}if (!this.isSingleDecode()) {continue;}}}}return;}} catch (DecoderException var6) {throw var6;} catch (Exception var7) {throw new DecoderException(var7);}}

结合Buf的原理,readindex如果不处理就会每次读取重复的数据,所以官方加判断并抛异常解决了这个死循环问题。

所以最常见的办法就是加上:skipBytes方法,将readindex往前移动数个位置

如:byteBuf.skipBytes(byteBuf.readableBytes());

下次直接从移动后的位置开始往后读取,就不会造成重复读取数据了

网上有人说要备份一下,否则影响其他decoder,这个还不理解为什么,这里mark一下

大概意思就是说,这个decoder把readindex往前移动了,但是其他decoder不能被影响,也要从头解析一遍,是这个意思吧

https://blog.csdn.net/zougen/article/details/79047252?utm_source=blogxgwz0

netty 异常 did not read anything but decoded a message相关推荐

  1. 【Netty - 解码器】did not read anything but decoded a message 异常

    一.代码 @Overrideprotected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List< ...

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

    Netty解码器报错:XXXDecoder.decode() did not read anything but decoded a message. 从字面意思来看,就是说没有读取任何数据,但是却解 ...

  3. Netty诡异报错did not read anything but decoded a message

    ###前言 用netty做数据校验的时候,很自然的想法是写一个decoder,比如XXXXChecksumDecoder,如果校验出错,就丢弃这个数据包,一般来说,这种单纯的做数据校验的decoder ...

  4. 解决:SpringBoot中使用WebSocket传输数据,提示 1009|The decoded text message was too big for the output buffer and

    SpringBoot项目中使用webSocket传输数据的时候,提示数据过大,断开了.服务器这边也接收不到数据. 报错如下: 1009|The decoded text message was too ...

  5. websocket 给服务端发送太长数据处理(The decoded text message was too big for the output buffer and the endpoint )

    根据tomcat中的说明: If the application does not define a MessageHandler.Partial for incoming text messages ...

  6. Netty源码解析8-ChannelHandler实例之CodecHandler

    请戳GitHub原文: github.com/wangzhiwubi- 更多文章关注:多线程/集合/分布式/Netty/NIO/RPC Java高级特性增强-集合 Java高级特性增强-多线程 Jav ...

  7. netty粘包拆包之LengthFieldBasedFrameDecoder解码器

    ​目录           一. 背景简介           二. 应用           三.源码 一.背景简介 LengthFieldBasedFrameDecoder 基于长度字段解码器,是 ...

  8. netty实现多协议,多编解码器

    实现多协议,多编解码器详解 前言 netty中handler的执行顺序和条件(重要) 执行顺序 入栈handler介绍 出栈handler介绍 入栈handler处理器顺序 出栈handler处理器顺 ...

  9. Java异常面试题(2020最新版)

    文章目录 Java异常架构与异常关键字 Java异常简介 Java异常架构 1. Throwable 2. Error(错误) 3. Exception(异常) 运行时异常 编译时异常 4. 受检异常 ...

  10. 【2022最新Java面试宝典】—— Java异常面试题(33道含答案)

    目录 一.Java异常架构与异常关键字 1. Java异常简介 2. Java异常架构 1.Throwable 2. Error(错误) 3. Exception(异常) 运行时异常 编译时异常 3. ...

最新文章

  1. 吸顶wifi_分享 | 酒店WiFi网络的三种部署模式
  2. github 视觉测量_计算机视觉八大任务全概述:PaddlePaddle工程师详解热门视觉模型...
  3. c语言结果用全局变量返回,c语言参数传递和返回值及变量存储.doc
  4. JavaScript实现切换数字的符号switchSign算法(附完整源码)
  5. 【原】IOS合并lib(.a)库的终极可用方法(可用于解决duplicate symbol静态库冲突)
  6. 批处理(bat)中路径名称或者文件名称有空格怎么办?
  7. 省赛来了(组合数)nyoj158
  8. Win2D 官方文章系列翻译 - DPI (每英寸点数)和 DIPs(设备独立像素)
  9. RPLIDAR的坐标系问题
  10. 第6章 项目进度管理
  11. HearthBuddy卡牌无法识别
  12. 带登录页面的猜数字小游戏
  13. python如何创建一个文件夹_利用Python怎么创建一个文件夹
  14. h5+(mui) 截图分享微信
  15. Html标签——table表格
  16. 硬件开发者之路之运放共模电压的解释
  17. rsync daemon模式介绍
  18. 虚拟机(Vmware)怎么进入BIOS
  19. 楚汉争霸显示未创建服务器,楚汉争霸单机游戏
  20. 51单片机-6-矩阵键盘

热门文章

  1. SSD Single shot detection 单发多框检测 实现 多尺度锚框 动手学深度学习v2
  2. Swift 5用Template自动创建VIPER架构代码
  3. 算法:动态规划 最大连续子数组和 Maximum Subarray
  4. 【易实战】Spring Cloud Greenwich Hystrix:服务容错保护
  5. mysql时间排序获取最新_mysql获取按日期排序获取时间最近的记录
  6. 318.最大单词长度乘积
  7. ctab法提取dna流程图_每周实验新品:创新核酸提取技术、离心管自动打标设备...
  8. git add 所有修改文件_工作中Git的使用实践
  9. python while 循环 全局变量_python循环语句(while amp; for)
  10. Pycharm连接远程服务器环境搭建