gpt4 book ai didi

java - 处理 ByteToMessageDecoder 中的异常

转载 作者:行者123 更新时间:2023-12-01 13:23:31 25 4
gpt4 key购买 nike

我编写了一个扩展 ByteToMessageDecoder 的解码器。基本上,我想做的只是在收到非预期消息时抛出异常(我假设 DecoderException),以停止解码消息并关闭连接。

当我抛出异常时,它会被以下处理程序捕获,该处理程序只会记录它并关闭连接。我可以看到它正在发生,但问题就来了......

由于某种原因,我收到另一条消息(相同的消息),该消息直接发送到解码器,解码器尝试再次解码它,但从下一个 readerIndex 开始,再次收到意外的消息并以相同的原因引发异常。

为什么我在连接即将关闭时在管道中收到另一条相同的消息?

如何防止这种情况发生?

public class Decoder extends ByteToMessageDecoder
{
private static Logger LOG = LoggerFactory.getLogger(Decoder.class);

private Codec codec;
private int contentSize = 0;

/**
* @see io.netty.handler.codec.ByteToMessageDecoder#decode(io.netty.channel.ChannelHandlerContext, io.netty.buffer.ByteBuf, java.util.List)
*/
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception
{
if (!buffer.isReadable())
return;

// read header
if (contentSize == 0) {
int id = buffer.readInt();
if (id == -1) {
LOG.warn("Received null message");
throw new DecoderException("Null message has been received.");
}
codec = CodecRegistry.getInstance().getCodec(id);
if (codec == null) {
LOG.error("No codec found for id: " + id);
throw new DecoderException("No codec found for id: " + id);
}
contentSize = buffer.readInt();
}

if (buffer.readableBytes() < contentSize) {
return;
}

// read content
ByteBufInputStream bbis = new ByteBufInputStream(buffer);
out.add(codec.decode(bbis));
contentSize = 0;
}
}

@Sharable
public class ClientHandler extends ChannelHandlerAdapter
{
private static Logger LOG = LoggerFactory.getLogger(ClientHandler.class);

/**
* @see io.netty.channel.ChannelHandlerAdapter#channelRead(io.netty.channel.ChannelHandlerContext, java.lang.Object)
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
{
LOG.info("I got the message!!! -> " + msg);
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
{
LOG.error("Unexpected exception from downstream." + cause);
ctx.close();
}
}

public class ClientInitializer extends ChannelInitializer<SocketChannel>
{
/**
* @see io.netty.channel.ChannelInitializer#initChannel(io.netty.channel.Channel)
*/
@Override
protected void initChannel(SocketChannel ch) throws Exception
{
ChannelPipeline pipeline = ch.pipeline();

pipeline.addLast("decoder", new Decoder());
pipeline.addLast("encoder", new Encoder());

// and then business logic.
pipeline.addLast("handler", new ClientHandler());
}
}

服务器发送一条仅包含 8 个字节的消息:

buffer.writeInt(-1);
buffer.writeInt(12345);

所以我期望一个DecoderException(“已收到空消息。”);

我在日志中看到的是:

INFO main Client - Starting Client..........WARN nioEventLoopGroup-2-1 Decoder - Received null messageERROR nioEventLoopGroup-2-1 ClientHandler - Unexpected exception from downstream.io.netty.handler.codec.DecoderException: org.jasypt.contrib.org.apache.commons.codec_1_3.DecoderException: Null message has been received.INFO nioEventLoopGroup-2-1 Client - Disconnected from the server.ERROR nioEventLoopGroup-2-1 Decoder - No codec found for id: 12345ERROR nioEventLoopGroup-2-1 ClientHandler - Unexpected exception from downstream.io.netty.handler.codec.DecoderException: org.jasypt.contrib.org.apache.commons.codec_1_3.DecoderException: No codec found for id: 12345

最佳答案

在尝试解码 header 之前,您必须确保缓冲区有超过 8 个字节。如果我是你,我会这样做:

    // read header
if (contentSize == 0) {
if (buffer.readableBytes() < 8) {
return;
}

int id = buffer.readInt();
...

关于java - 处理 ByteToMessageDecoder 中的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21909948/

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