当前位置: 首页 > 知识库问答 >
问题:

decode()没有读取任何内容,只是解码了一条消息

俞新翰
2023-03-14

对于套接字服务器应用程序,我创建了一个PacketFragmenter,它读取数据包的长度(在数据包的第二个字节中),然后将数据包发送回管道。

下面是我写的代码:

public class PacketFragmenter extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in,
            List<Object> out) throws Exception {
        //I read a byte just to make the reader index go to second byte
        in.readByte();

        //in the second byte i get the content's length
        int length = in.readByte();

        //if my content is smaller than the readableBytes, there's a problem, so i return
        if (in.readableBytes() < length) {
            return;
        }

        //If everything is good, i reset the reader index to be able to write the whole packet in the out buffer (because i need the first byte in next handler, same for the size)
        in.resetReaderIndex();
        //I send my packet to the next handler
        out.add(in.readBytes(length +2));
        //and i reset the rederIndex to be able to read another packet
        in.resetReaderIndex();
    }

}

我在测试中得到了这个堆栈:

io.netty.handler.codec.DecoderException: PacketFragmenter.decode() did not read anything but decoded a message.
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:334)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:229)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:339)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:324)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:847)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)

但一切都像它应该的那样进行,我得到两个数据包在一行,但他们很好地拼接,下一个处理程序正在做他的工作。

所以我不知道我应该处理这个例外还是忽略它?或者我可以做一件简单的事情来修复它,我根本不是网络专家(一周前开始),所以这应该很容易修复。但是我在netty的用户指南上什么也没找到。

共有2个答案

羊和光
2023-03-14
public class PacketFrameDecoder extends LengthFieldBasedFrameDecoder {

    private static final int MAX_PACKET_LENGTH = 8192 * 2;
    private static final int LENGTH_FIELD_OFFSET = 1;
    private static final int LENGTH_FIELD_LENGTH = 1;
    private static final int LENGTH_FIELD_ADJUSTMENT = 0;
    private static final int INITIAL_BYTES_TO_STRIP = 0;

    public PacketFrameDecoder()
    {
        super(MAX_PACKET_LENGTH, LENGTH_FIELD_OFFSET, LENGTH_FIELD_LENGTH, LENGTH_FIELD_ADJUSTMENT, INITIAL_BYTES_TO_STRIP);
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception 
    {
        return super.decode(ctx, in);
    }
}

这里是我如何修复它,事实上有一个LengthFieldBasedFrameDecoder完成,不需要扩展ByteToMessageDecoder。

袁玮
2023-03-14

我想在苏帕密的回答中再补充一点信息。在许多情况下,使用LengthFieldBasedFrameDecoder作为父类是正确的方法,但并没有解释引发异常的原因。

如果您产生一条消息,您还需要从ByteBuf中读取一些内容。添加此检查是为了捕获用户解码器错误生成的无尽循环。

因此,如果删除中的最后一行。resetReaderIndex() 从原始方法,异常将消失:

public class PacketFragmenter extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        in.skipBytes(1);
        //in the second byte i get the content's length
        int length = in.readByte();

        //if my content is smaller than the readableBytes, there's a problem, so i return
        if (in.readableBytes() < length) {
            return;
        }

        //If everything is good, i reset the reader index to be able to write the whole packet in the out buffer (because i need the first byte in next handler, same for the size)
        in.resetReaderIndex();
        //I send my packet to the next handler
        out.add(in.readBytes(length + 2));
    }
}

 类似资料:
  • 本文向大家介绍详解Python解决抓取内容乱码问题(decode和encode解码),包括了详解Python解决抓取内容乱码问题(decode和encode解码)的使用技巧和注意事项,需要的朋友参考一下 一、乱码问题描述 经常在爬虫或者一些操作的时候,经常会出现中文乱码等问题,如下 原因是源网页编码和爬取下来后的编码格式不一致  二、利用encode与decode解决乱码问题 字符串在Python

  • 问题内容: 我正在解析json数据。我的解析没有问题,我正在使用模块。但是某些api请求返回空值。这是我的示例: 这是我解析json对象的代码段: 正如我提到的一些请求,我得到以下错误: 处理此错误的最佳方法是什么? 问题答案: Python编程中有一条规则叫做“求宽容比求许可要容易”(简而言之:EAFP)。这意味着您应该捕获异常,而不是检查值的有效性。 因此,请尝试以下操作: 编辑 :由于实际上

  • 我对阿帕奇Storm和Kafka有意见。KafkaSpout正常读取来自Kafka的消息,但在大约30,000条消息之后,失败的元组开始出现,博尔特没有收到任何消息。 我查看worker.log并看到,当拓扑启动时,它尝试从Zookeeper读取分区信息,然后在broker中读取分区信息,成功了,如您所见:偏移量9539 Tweets正常保存,然后Kafka Spout尝试从Zookeeper读取

  • 我有一个数据流工作: 从GCS读取包含其他文件名的文本文件 将文件名传递给ReadAllFromParquet以读取。Parquet文件 写入BigQuery 尽管我的工作“成功”了,但它基本上没有经过ReadAllFromParquet步骤的输出集合。我成功地读取了列表中的文件,例如:我还在readallfromparquet之前的步骤中使用记录器确认此列表和文件的GCS路径是正确的。 这就是我

  • 问题内容: 我正在使用jsoup抓取一些HTML数据,效果很好。现在,我需要提取一些JSON内容(仅JSON,而不是HTML)。我可以使用jsoup轻松做到这一点,还是必须使用另一种方法来做到这一点?jsoup执行的解析是对JSON数据进行编码,因此无法使用Gson正确解析。 谢谢! 问题答案: 虽然很棒,但Jsoup是HTML解析器,而不是JSON解析器,因此在这种情况下它没有用。如果您尝试过,

  • 我做的一个网站需要显示WordPress帖子信息(标题,标签,缩略图)。从发布的帖子中获取这些信息的PHP代码可以在我的localhost上正常显示帖子数据。 我只是把网站上传到我的主机的服务器上,配置WP设置与我的localhostWP安装相同,而99%的网站按预期工作,帖子的信息不显示。 目前现场共有3个测试站。我可以通过DOM检查器看到3个文章标记,因此检索帖子的WP循环工作得很好。但是,在