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

如何让我的bytebuf将我的全部信息发送给Netty

白灿
2023-03-14

我每个人。

我问你是因为我在Netty的解码器中的ByteBuf有问题。

我想解码我的消息谁到达一个服务器,但ByteBuf不工作,因为我会。

问题是ByteBuf没有获取消息的所有字节。

我解释说,我有一条长度为1221字节的消息(这是一个示例),但缓冲区大小只有64字节。

当我试图阅读,缓冲区与我的长度和我有这样的错误:

io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(117) + length(101) exceeds writerIndex(192): PooledUnsafeDirectByteBuf(ridx: 117, widx: 192, cap: 192)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:470) ~[netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:697) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:632) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:549) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:511) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:918) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [netty-all-4.1.37.Final.jar:4.1.37.Final]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]

我认为Netty没有时间阅读所有内容并只发送部分消息,但我现在不知道是否可以配置Netty,因为他必须等到消息全部到达。

如果有人能帮我,我很感激

为了获得更多帮助,我给您提供了解码器的代码

    int length = buffer.readInt();
    int messageType = buffer.readInt();


        Supplier<AbstractMessage> supplier = SUPPLIERS.get(messageType);
        if (supplier == null) {
            LOGGER.debug("This message type isn't supported: {}", messageType);
        } else {
            ByteBuf data = buffer.readBytes(length);
            if (messageType != 6) {
                AbstractMessage message = supplier.get();
                message.read(data, version);
                list.add(message);
                LOGGER.debug("{}", message);
            }
        }
    }

}

消息格式如下:MessageLength in 4字节(int)MessageType in 4字节(int)Data in n字节(MessageLength size)

我给你我用来解释这里的文档。

共有2个答案

秦胡媚
2023-03-14

非常感谢。我做了一些改变,但你的代码激励了我,解决了我的问题。我想我收到了碎片信息,但我并没有太多的知识。

如果这篇文章能帮助别人,我把下面的代码更正

if (length == 0) {
        length = buffer.readInt();
        messageType = buffer.readInt();
    }

    if (buffer.writerIndex() < length + buffer.readerIndex()) {
        // ensure we have enough data so we can also read the message type and the whole message body
        return;
    }

    if (!(messageType == MessageType.HEARTBEAT_REQ.getValue() || messageType == MessageType.HEARTBEAT_CONF.getValue())) {
        LOGGER.debug("The message type is : {}", messageType);
    }

    Supplier<AbstractMessage> supplier = SUPPLIERS.get(messageType);
    if (supplier == null) {
        LOGGER.debug("This message type isn't supported: {}", messageType);
        buffer.skipBytes(length);
    } else {
        ByteBuf data = buffer.readSlice(length);
        AbstractMessage message = supplier.get();
        message.read(data, version);
        list.add(message);
        if (messageType != 6) {
            LOGGER.debug("{}", message);
        }
        length = 0;
        messageType = 0;
    }

请注意,length和messageType变量现在在解码器中是静态的

private static int length = 0;
private static int messageType = 0;
养慈
2023-03-14

您需要通过扩展ByteToMessageDecoder和缓冲区来编写自己的解码器,直到您收到所有内容。由于这是TCP,您可能会以碎片的方式接收字节,因此您需要自己重新组装它。

像这样的方法应该会奏效:

class MyDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf input, List<Object> out) {
        if (input.readableBytes() < 4) {
            // we need to have at least 4 bytes to read to be able to get the message length
            return;
        }
        int length = input.getInt(input.readerIndex());
        if (input.readableBytes() < 8 + length) {
            // ensure we have enough data so we can also read the message type and the whole message body
            return;
        }
        // skip the length now
        input.skipBytes(4);

        int messageType = input.readInt();

        Supplier<AbstractMessage> supplier = SUPPLIERS.get(messageType);
        if (supplier == null) {
            LOGGER.debug("This message type isn't supported: {}", messageType);
            input.skip(length);
        } else {
            if (messageType != 6) {
                ByteBuf data = buffer.readSlice(length);
                AbstractMessage message = supplier.get();
                message.read(data, version);
                list.add(message);
                LOGGER.debug("{}", message);
            }
        }
    }
}
 类似资料:
  • 我正试着把二维码的信息存储在火力点上。我想存储从二维码到Firebase的Url。 我已经被困在这两天了,请帮帮我。 这是我目前为止的代码。 二维码我用Zxing。

  • 当前,我正在发送不带任何密钥的邮件作为密钥邮件的一部分,它是否仍能与一起工作?我需要发送密钥作为消息的一部分吗?把key作为信息的一部分好吗?

  • 读取用户信息 调用地址 http://api.bilibili.cn/myinfo 需要 App Key 并验证登录状态(Access key) 返回 返回值字段 字段类型 字段说明 mid int 用户ID uname string 用户名称 face string 头像图片地址 rank int 用户等级 scores int 积分 coins int 金币 attentions int 关注

  • 当我尝试编译这段代码时,Eclipse会出现以下两个错误: > 用于函数:maxmin的非法修饰符;只允许最终 对于:Mn不能解析为变量 为什么会出现这两个错误? 我想这可能已经回答了这个问题,但我不明白其中使用的术语。 这是我的代码:

  • 我有一个活动,收听udp广播,如果达到某个阈值,就会触发警报。但是当我退出应用程序时,我不再收到通知。我如何保持应用程序在后台运行,以便它将发送一个通知时,跨越阈值?我读过一些关于服务的文章,但我不确定在活动和服务之间的关系中逻辑是如何工作的。服务是否应该始终运行,服务是否应该在应用关闭时启动?我希望应用程序触发警报,即使另一个应用程序正在运行。

  • 我正在发出一个有反应的帮助命令,机器人将添加一个反应,然后用户将作出反应,机器人将发布相应的帮助消息。我很困惑为什么我的代码不能工作,因为它没有抛出错误。 收到任何帮助都表示感谢:) Ps:我在嵌入的后面使用这个,所以我希望嵌入对它有一个反应,尽管我已经做了这一点,只是不知道如何在嵌入和反应之间有效地链接代码