gpt4 book ai didi

netty - 从 LengthFieldBasedFrameDecoder 返回的缓冲区太小

转载 作者:行者123 更新时间:2023-12-04 05:15:21 24 4
gpt4 key购买 nike

我目前正在评估 Netty 以处理 Java 客户端与 C++ 服务器集成的套接字通信。消息传递协议(protocol)具有以下结构 -

  • (Type)(SubType)(Length)(MessageBody) 大小为
  • <4bytes><4bytes><4bytes><...> - 长度包括标题。

  • 在 Netty api 之后,我将 LengthFieldBasedFrameDecoder 子类化以接收有效的完整数据包,然后根据接收到的类型对每个数据包进行解码。从我正在使用的文档中 -
  • lengthFieldOffset = 8
  • 长度字段长度 = 4
  • lengthAdjustment = -12(= HDR1 + LEN 的长度,负数)
  • initialBytesToStrip = 0

  • 它可以正常工作大约 5 分钟(我每 5 秒左右收到一条消息),然后解码事件包含一个比消息大小短得多的 ChannelBuffer。 (我在崩溃前多次收到此消息)。然后我显然在我的内部解码代码中得到了一个 BufferUnderflowException 。难道我做错了什么?使用 LengthFieldBasedFrameDecoder 时,是否应该保证消息的缓冲区大小正确?

    LengthFieldBasedFrameDecoder 类 -
    public class CisPacketDecoder extends LengthFieldBasedFrameDecoder
    {
    public CisPacketDecoder(int maxFrameLength, int lengthFieldOffset,
    int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) {
    super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment,
    initialBytesToStrip);
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf)
    throws Exception
    {
    CisMessage message = null;
    int type = buf.getInt(0); //Type is always first int
    CisMessageType messageType = CisMessageType.fromIntToType(type);
    if(messageType != null)
    {
    message = messageType.getObject();
    if(message != null)
    {
    message.decode(buf.toByteBuffer());
    }
    else
    {
    System.out.println("Unable to create message for type " + type);
    }
    }

    //mark the Channel buf as read by moving reader index
    buf.readerIndex(buf.capacity());
    return message;
    }

    }

    并在这里实例化。
    public class PmcPipelineFactory implements ChannelPipelineFactory 
    {

    @Override
    public ChannelPipeline getPipeline() throws Exception
    {
    ChannelPipeline pipeline = Channels.pipeline();

    pipeline.addLast("encoder", new CisPacketEncoder());
    pipeline.addLast("decoder", new CisPacketDecoder(1024, 8, 4, -12, 0));
    pipeline.addLast("handler", new MsgClientHandler());
    return pipeline;
    }


    }

    最佳答案

    您需要调用 super.decode(..) 并在 decode(..) 方法中对返回的 ChannelBuffer 进行操作。

    所以它会是这样的;

    public class CisPacketDecoder extends LengthFieldBasedFrameDecoder {
    public CisPacketDecoder(int maxFrameLength, int lengthFieldOffset,
    int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) {
    super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment,
    initialBytesToStrip);
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf)
    throws Exception {

    // THIS IS IMPORTANT!!!!!
    ChannelBuffer decoded = (ChannelBuffer) super.decode(ctx, channel, buf);
    if (decoded == null) {
    return null;
    }

    // NOW ONLY OPERATE ON decoded
    CisMessage message = null;
    int type = decoded.getInt(0); //Type is always first int
    CisMessageType messageType = CisMessageType.fromIntToType(type);
    if(messageType != null) {
    message = messageType.getObject();
    if(message != null) {
    message.decode(decoded.toByteBuffer());
    } else {
    System.out.println("Unable to create message for type " + type);
    }
    }
    return message;
    }
    }

    请务必检查大写注释。

    关于netty - 从 LengthFieldBasedFrameDecoder 返回的缓冲区太小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14352450/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com