1

プロジェクトで Netty3 を Netty4 に置き換えています。データ転送として Google-protocol-buffer を使用しています。Netty3 で正常に動作するチャネルを閉じるときに例外が発生しました。

例外の詳細は次のとおりです。

io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(0) + length(4) exceeds writerIndex(0): PooledUnsafeDirectByteBuf(ridx: 0, widx: 0, cap: 4096)
    at io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:95)
    at io.netty.channel.DefaultChannelHandlerContext.invokeChannelInactive(DefaultChannelHandlerContext.java:801)
    at io.netty.channel.DefaultChannelHandlerContext.fireChannelInactive(DefaultChannelHandlerContext.java:787)
    at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:808)
    at io.netty.channel.AbstractChannel$AbstractUnsafe$9.run(AbstractChannel.java:725)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:364)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:326)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:114)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IndexOutOfBoundsException: readerIndex(0) + length(4) exceeds writerIndex(0): PooledUnsafeDirectByteBuf(ridx: 0, widx: 0, cap: 4096)
    at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1120)
    at io.netty.buffer.AbstractByteBuf.readInt(AbstractByteBuf.java:627)
    at com.fhq.mathematica.netty.MMADecoder.decode(MMADecoder.java:17)
    at io.netty.handler.codec.ByteToMessageDecoder.decodeLast(ByteToMessageDecoder.java:168)
    at io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:91)

これがエンコーダーです:(メッセージは最上位のプロトコルバッファーのインターフェースです。)

public class MessageEncoder extends MessageToByteEncoder<Message>{
    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out)
            throws Exception {
        byte[] data = msg.toByteArray();
        out.writeInt(data.length);
        out.writeBytes(data);
    }
}

デコーダーは次のとおりです。

public class MMADecoder extends ByteToMessageDecoder{
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in,
            MessageBuf<Object> out) throws Exception {
        in.markReaderIndex();
        int dataLength = in.readInt();
        if (in.readableBytes() < dataLength) {
            in.resetReaderIndex();
            return;
        }
        byte[] decoded = new byte[dataLength];
        in.readBytes(decoded);
        out.add(MathematicaTask.parseFrom(decoded));
    }
}

MathematicaTask オブジェクトを転送すると、正常に動作します(クライアントとサーバーの両方がメッセージを正しく解析します)。しかし、チャネルを閉じると、デコーダーで例外が発生します。

int dataLength = in.readInt();

誰でも問題を理解できますか?ムッシュ大歓迎!

ところで:私は ObjectEncoder と ObjectDecoder を試しましたが、すべて問題ありません。したがって、私のデコーダー/エンコーダーに問題があるに違いありません。

4

1 に答える 1

0

ByteBuf.readInt() を呼び出す前に、読み取るのに十分なバイトがあるかどうかを確認する必要があります。

だから、このようなもの:

public class MMADecoder extends ByteToMessageDecoder{
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in,
            MessageBuf<Object> out) throws Exception {
        if (in.readableBytes < 4) {
            return;
        }
        in.markReaderIndex();
        int dataLength = in.readInt();
        if (in.readableBytes() < dataLength) {
            in.resetReaderIndex();
            return;
        }
        byte[] decoded = new byte[dataLength];
        in.readBytes(decoded);
        out.add(MathematicaTask.parseFrom(decoded));
    }
}
于 2013-05-31T12:21:03.417 に答える