简体   繁体   中英

java.lang.IndexOutOfBoundsException Exception using Netty in a packet system

I am currently programming a system that communicates via packets. This also works. I have one server and theoretically infinite clients. When I start only one client, it works very well, but when I start several, I always get a java.lang.IndexOutOfBoundsException exception after the program has worked for 2-3 minutes.

The Exception

WARNUNG: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(77) + length(36) exceeds writerIndex(112): PooledUnsafeDirectByteBuf(ridx: 77, widx: 112, cap: 112)
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:478)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:102)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
        at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795)
        at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480)
        at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.lang.Thread.run(Thread.java:748)

Caused by: java.lang.IndexOutOfBoundsException: readerIndex(77) + length(36) exceeds writerIndex(112): PooledUnsafeDirectByteBuf(ridx: 77, widx: 112, cap: 112)
        at io.netty.buffer.AbstractByteBuf.checkReadableBytes0(AbstractByteBuf.java:1442)
        at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1428)
        at io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:895)
        at io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:903)
        at eu.diamondcloudservice.wrapper.packets.incoming.PacketInCloudServerConnect.read(PacketInCloudServerConnect.java:79)
        at eu.diamondcloudservice.wrapper.network.PacketDecoder.decode(PacketDecoder.java:21)
        at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508)
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447)
        ... 19 more

Server main(String[] args)

EventLoopGroup eventLoopGroup = epoll ? (EventLoopGroup) new EpollEventLoopGroup() : (EventLoopGroup) new NioEventLoopGroup();
    try {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(eventLoopGroup);
        serverBootstrap.channel(epoll ? EpollServerSocketChannel.class : NioServerSocketChannel.class);
        serverBootstrap.childHandler(new ChannelInitializer<Channel>() {
            protected void initChannel(Channel channel) throws Exception {
                channel.pipeline().addLast(new NetworkHandler());
            }
        });
        channel = serverBootstrap.bind(networkConfiguration.getPort()).sync().channel();
        channel.closeFuture().syncUninterruptibly();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        eventLoopGroup.shutdownGracefully();
    }

Client main(String[] args):

EventLoopGroup eventLoopGroup = epoll ? (EventLoopGroup) new EpollEventLoopGroup() : (EventLoopGroup) new NioEventLoopGroup();
    try {

        io.netty.bootstrap.Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(eventLoopGroup);
        bootstrap.channel(epoll ? EpollSocketChannel.class : NioSocketChannel.class);
        bootstrap.handler(new ChannelInitializer<Channel>() {
            protected void initChannel(Channel channel) throws Exception {
                channel.pipeline().addLast(new NetworkHandler());
            }
        });

        channel = bootstrap.connect(networkConfiguration.getMasterHostname(), networkConfiguration.getMasterPort()).sync().channel();
        packetCaller = new PacketCaller(channel);
        packetCaller.sendPacket(new PacketOutVerify(networkConfiguration.getWrapperName(), networkConfiguration.getKey()));
        channel.closeFuture().syncUninterruptibly();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        eventLoopGroup.shutdownGracefully();
    }

channelActive in NetworkHandler:

public void channelActive(ChannelHandlerContext ctx) throws Exception {
    ctx.pipeline().addLast(new PacketEncoder());
    ctx.pipeline().addLast(new PacketDecoder());
    this.waitingForRegistration.add(ctx.channel());
}

PacketDecoder

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> output) throws     Exception {
int id = byteBuf.readInt();
Class<? extends Packet> clazz = Wrapper.IN_PACKETS.get(id);
if (clazz == null) {
  throw new NullPointerException("Could not find packet by id " + id);
}

Packet packet = clazz.newInstance();
packet.read(byteBuf, ctx.channel());
}

PacketEncoder

public class PacketEncoder extends MessageToByteEncoder<Packet> {
@Override
protected void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf output) throws Exception   {
  int id = Wrapper.OUT_PACKETS.indexOf(packet.getClass());
  if(id == -1)
    throw new NullPointerException("Couldn't find packet of " + packet.getClass().getName());

  output.writeInt(id);
  packet.write(output, ctx.channel());
}
}

So there are multiple issues.

First of in PacketDecoder you need to first check if there are 4 bytes readable before trying to call byteBuf.readInt() . So something like:

protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf,      List<Object> output) throws Exception {
    if (byteBuf.readableBytes() < 4) {
        return;
    }
    int id = byteBuf.readInt();
    ...
}

Secondly in your Packet.read() method you also need to ensure that there are enough bytes readable and if not try again later

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM