EmptyByteBuf 出现在 Netty 服务器的 Decoder 链中
EmptyByteBuf appears in Decoder chain in Netty server
Netty 版本:5.0.0.Alpha2
以下是我将 handlers/decoders 添加到我的管道的方法。 (childHandler)
childHandler(ch ->
ch.pipeline().addLast(
new LoggingHandler(LogLevel.TRACE),
new LengthFieldBasedFrameDecoder(2048, 4, 2, -2, 0),
new MyDecoder2(),
new Encoder(),
handler
)
)
我接下来要做的是向该服务器的输入发送一些垃圾。 LengthFieldBasedFrameDecoder 抛出 TooLongFrameException,在这种情况下是预期的。
但是,在 LengthFieldBasedFrameDecoder 抛出异常之后,MyDecoder2.decode()
被调用为 EmptyByteBuf
作为输入缓冲区。
如果之前的 Decoder 应该 return nothing,这个 EmptyByteBuf
来自哪里?
我希望 MyDecoder2
要么接收具有正确帧的 ByteBuf,由 LengthFieldBasedFrameDecoder
处理要么什么也接收不到。
Caused by: java.lang.IndexOutOfBoundsException: null
at io.netty.buffer.EmptyByteBuf.checkIndex(EmptyByteBuf.java:866) ~[na:0.0]
at io.netty.buffer.EmptyByteBuf.getBytes(EmptyByteBuf.java:317) ~[na:0.0]
at spire.broker.proto.MyDecoder2.decode(MyDecoder2.java:27) ~[na:0.0]
at io.netty.handler.codec.ByteToMessageDecoder.decodeLast(ByteToMessageDecoder.java:371) ~[na:0.0]
at io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:275) ~[na:0.0]
也许我没有正确理解 Netty 如何与管道中的解码器链一起工作。
看一下 ByteToMessageDecoder
的 channelInactive()
方法的代码,LengthFieldBasedFrameDecoder
扩展:
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
RecyclableArrayList out = RecyclableArrayList.newInstance();
try {
if (cumulation != null) {
callDecode(ctx, cumulation, out);
decodeLast(ctx, cumulation, out);
} else {
decodeLast(ctx, Unpooled.EMPTY_BUFFER, out);
}
} catch (DecoderException e) {
throw e;
} catch (Exception e) {
throw new DecoderException(e);
} finally {
...
}
}
一旦通道变为非活动状态,它将使用 Unpooled.EMPTY_BUFFER
最后一次调用解码方法。如果您制作了自定义解码器,这使您有机会进行清理。如果您对此不感兴趣,那么您需要覆盖 decodeLast()
方法以不执行任何操作。
Netty 版本:5.0.0.Alpha2
以下是我将 handlers/decoders 添加到我的管道的方法。 (childHandler)
childHandler(ch ->
ch.pipeline().addLast(
new LoggingHandler(LogLevel.TRACE),
new LengthFieldBasedFrameDecoder(2048, 4, 2, -2, 0),
new MyDecoder2(),
new Encoder(),
handler
)
)
我接下来要做的是向该服务器的输入发送一些垃圾。 LengthFieldBasedFrameDecoder 抛出 TooLongFrameException,在这种情况下是预期的。
但是,在 LengthFieldBasedFrameDecoder 抛出异常之后,MyDecoder2.decode()
被调用为 EmptyByteBuf
作为输入缓冲区。
如果之前的 Decoder 应该 return nothing,这个 EmptyByteBuf
来自哪里?
我希望 MyDecoder2
要么接收具有正确帧的 ByteBuf,由 LengthFieldBasedFrameDecoder
处理要么什么也接收不到。
Caused by: java.lang.IndexOutOfBoundsException: null
at io.netty.buffer.EmptyByteBuf.checkIndex(EmptyByteBuf.java:866) ~[na:0.0]
at io.netty.buffer.EmptyByteBuf.getBytes(EmptyByteBuf.java:317) ~[na:0.0]
at spire.broker.proto.MyDecoder2.decode(MyDecoder2.java:27) ~[na:0.0]
at io.netty.handler.codec.ByteToMessageDecoder.decodeLast(ByteToMessageDecoder.java:371) ~[na:0.0]
at io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:275) ~[na:0.0]
也许我没有正确理解 Netty 如何与管道中的解码器链一起工作。
看一下 ByteToMessageDecoder
的 channelInactive()
方法的代码,LengthFieldBasedFrameDecoder
扩展:
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
RecyclableArrayList out = RecyclableArrayList.newInstance();
try {
if (cumulation != null) {
callDecode(ctx, cumulation, out);
decodeLast(ctx, cumulation, out);
} else {
decodeLast(ctx, Unpooled.EMPTY_BUFFER, out);
}
} catch (DecoderException e) {
throw e;
} catch (Exception e) {
throw new DecoderException(e);
} finally {
...
}
}
一旦通道变为非活动状态,它将使用 Unpooled.EMPTY_BUFFER
最后一次调用解码方法。如果您制作了自定义解码器,这使您有机会进行清理。如果您对此不感兴趣,那么您需要覆盖 decodeLast()
方法以不执行任何操作。