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.