netty 异常 did not read anything but decoded a message
翻译过来就是说:什么也没读,只是解码了一条信息
编码器是如下图
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相关推荐
- 【Netty - 解码器】did not read anything but decoded a message 异常
一.代码 @Overrideprotected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List< ...
- 【Netty报错:】XXXDecoder.decode() did not read anything but decoded a message.
Netty解码器报错:XXXDecoder.decode() did not read anything but decoded a message. 从字面意思来看,就是说没有读取任何数据,但是却解 ...
- Netty诡异报错did not read anything but decoded a message
###前言 用netty做数据校验的时候,很自然的想法是写一个decoder,比如XXXXChecksumDecoder,如果校验出错,就丢弃这个数据包,一般来说,这种单纯的做数据校验的decoder ...
- 解决:SpringBoot中使用WebSocket传输数据,提示 1009|The decoded text message was too big for the output buffer and
SpringBoot项目中使用webSocket传输数据的时候,提示数据过大,断开了.服务器这边也接收不到数据. 报错如下: 1009|The decoded text message was too ...
- 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 ...
- Netty源码解析8-ChannelHandler实例之CodecHandler
请戳GitHub原文: github.com/wangzhiwubi- 更多文章关注:多线程/集合/分布式/Netty/NIO/RPC Java高级特性增强-集合 Java高级特性增强-多线程 Jav ...
- netty粘包拆包之LengthFieldBasedFrameDecoder解码器
目录 一. 背景简介 二. 应用 三.源码 一.背景简介 LengthFieldBasedFrameDecoder 基于长度字段解码器,是 ...
- netty实现多协议,多编解码器
实现多协议,多编解码器详解 前言 netty中handler的执行顺序和条件(重要) 执行顺序 入栈handler介绍 出栈handler介绍 入栈handler处理器顺序 出栈handler处理器顺 ...
- Java异常面试题(2020最新版)
文章目录 Java异常架构与异常关键字 Java异常简介 Java异常架构 1. Throwable 2. Error(错误) 3. Exception(异常) 运行时异常 编译时异常 4. 受检异常 ...
- 【2022最新Java面试宝典】—— Java异常面试题(33道含答案)
目录 一.Java异常架构与异常关键字 1. Java异常简介 2. Java异常架构 1.Throwable 2. Error(错误) 3. Exception(异常) 运行时异常 编译时异常 3. ...
最新文章
- 吸顶wifi_分享 | 酒店WiFi网络的三种部署模式
- github 视觉测量_计算机视觉八大任务全概述:PaddlePaddle工程师详解热门视觉模型...
- c语言结果用全局变量返回,c语言参数传递和返回值及变量存储.doc
- JavaScript实现切换数字的符号switchSign算法(附完整源码)
- 【原】IOS合并lib(.a)库的终极可用方法(可用于解决duplicate symbol静态库冲突)
- 批处理(bat)中路径名称或者文件名称有空格怎么办?
- 省赛来了(组合数)nyoj158
- Win2D 官方文章系列翻译 - DPI (每英寸点数)和 DIPs(设备独立像素)
- RPLIDAR的坐标系问题
- 第6章 项目进度管理
- HearthBuddy卡牌无法识别
- 带登录页面的猜数字小游戏
- python如何创建一个文件夹_利用Python怎么创建一个文件夹
- h5+(mui) 截图分享微信
- Html标签——table表格
- 硬件开发者之路之运放共模电压的解释
- rsync daemon模式介绍
- 虚拟机(Vmware)怎么进入BIOS
- 楚汉争霸显示未创建服务器,楚汉争霸单机游戏
- 51单片机-6-矩阵键盘
热门文章
- SSD Single shot detection 单发多框检测 实现 多尺度锚框 动手学深度学习v2
- Swift 5用Template自动创建VIPER架构代码
- 算法:动态规划 最大连续子数组和 Maximum Subarray
- 【易实战】Spring Cloud Greenwich Hystrix:服务容错保护
- mysql时间排序获取最新_mysql获取按日期排序获取时间最近的记录
- 318.最大单词长度乘积
- ctab法提取dna流程图_每周实验新品:创新核酸提取技术、离心管自动打标设备...
- git add 所有修改文件_工作中Git的使用实践
- python while 循环 全局变量_python循环语句(while amp; for)
- Pycharm连接远程服务器环境搭建