【问题标题】:Netty Encoder And Decoder using Kryo Serialization使用 Kryo 序列化的 Netty 编码器和解码器
【发布时间】:2023-03-25 22:11:01
【问题描述】:

我是 Netty 4.0.29 的新手,并试图使用 Kryo 作为序列化库来制作自定义对象编码器和对象解码器,但我无法使其工作。由于我是 Netty 的新手,也许这就是我搞砸了一些事情的原因。我正在使用 MessageToMessageEncoderMessageToMessageDecoder

这是我的编码器 -

public class KryoEncoder extends  MessageToMessageEncoder<Object>{

    private Kryo kryo;
    private Output output;

    public KryoEncoder(Kryo kryo, int bufSize, int maxBufSize) {
        this.kryo = kryo;
        output = new Output(bufSize, maxBufSize);
    }

    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg,
            List<Object> out) throws Exception {
        output.clear();
        kryo.writeClassAndObject(output, msg);
        int total = output.position();
        out.add(Unpooled.wrappedBuffer(output.getBuffer(), 0 , total));
    }

}

这里是解码器-

public class KryoDecoder extends MessageToMessageDecoder<Object>{
    private Kryo kryo;
    private Input input;

    public KryoDecoder (Kryo kryo) {
        this.kryo = kryo;
        input = new Input();
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, Object msg, List<Object> out) throws Exception {
        ByteBuf buffer = (ByteBuf)msg;
        byte[] ar = new byte[buffer.readableBytes()];
        buffer.readBytes(ar);
        input.read(ar, buffer.readerIndex(), buffer.readableBytes());
        Object object = kryo.readClassAndObject(input);
        buffer.readerIndex(input.position());
        out.add(object);
    }
}

这是抛出的短堆栈异常,我知道这是一个空指针异常,并且解码器中的字节数组有问题,但不确定是什么。

Caused by: java.lang.NullPointerException
    at java.lang.System.arraycopy(Native Method)
    at com.esotericsoftware.kryo.io.Input.read(Input.java:254)
    at TestWithKryo.KryoDecoder.decode(KryoDecoder.java:31)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89)
    ... 14 more

解码时发生异常,我在发送编码对象时检查了编码器并检查了channelFuture,它没有抛出任何异常。

再次,因为我对netty真的很陌生,我可能做错了什么,所以请告诉我。

【问题讨论】:

    标签: java netty kryo


    【解决方案1】:

    我认为更好的是 ByteToMessageDecoder 和 MessageToByteEncoder。不要忘记发送第一个数据长度,或者您不知道一个数据包从哪里开始,另一个数据包在哪里结束。有我的简单例子:

    public class KryoDecoder extends ByteToMessageDecoder {
    
        private final Kryo kryo;
    
        public KryoDecoder(Kryo kryo) {
            this.kryo = kryo;
        }
    
        @Override
        protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    
            if (in.readableBytes() < 2)
                return;
    
            in.markReaderIndex();
    
            int len = in.readUnsignedShort();
    
            if (in.readableBytes() < len) {
                in.resetReaderIndex();
                return;
            }
    
            byte[] buf = new byte[len];
            in.readBytes(buf);
            Input input = new Input(buf);
            Object object = kryo.readClassAndObject(input);
            out.add(object);
    
        }
    }
    

    和编码器

    public class KryoEncoder extends MessageToByteEncoder<Object> {
    
        private final Kryo kryo;
    
        public KryoEncoder(Kryo kryo) {
            this.kryo = kryo;
        }
    
        @Override
        protected void encode(ChannelHandlerContext ctx, Object in, ByteBuf out) throws Exception {
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            Output output = new Output(outStream, 4096);
    
            kryo.writeClassAndObject(output, in);
            output.flush();
    
            byte[] outArray = outStream.toByteArray();
            out.writeShort(outArray.length);
            out.writeBytes(outArray);
        }
    
    }
    

    【讨论】:

    • 你也可以给我一个简短的说明为什么我的解决方案不起作用,因为我想知道我做错了什么。
    • 主要问题是input.read(ar, buffer.readerIndex(), buffer.readableBytes());的使用。您试图从输入中的缓冲区读取,此时为空。
    • 我没有接受你的回答,因为我一连接 3 个客户端,解码器就会爆炸。在解码器中的这一行抛出空指针异常 Object object = kryo.readClassAndObject(input);
    • 你能把这个异常的完整堆栈跟踪发给我吗?
    • 也只是为了让你知道,我用数据包淹没了服务器。我向服务器发送一个数据包,服务器将其回显,然后从客户端将其回显给服务器。所以它进入了一个无限循环。
    猜你喜欢
    • 2018-04-12
    • 1970-01-01
    • 2017-10-19
    • 2016-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-19
    相关资源
    最近更新 更多