Reputation: 170
I am getting an indexOutOfBoundException using netty when trying to send over a png from server to client. The error occurs on the line where it reads the bytes p.readBytes()
in client.
Exception in thread "LWJGL Application" java.lang.IndexOutOfBoundsException: readerIndex(97) + length(199852) exceeds writerIndex(185453): PooledUnsafeDirectByteBuf(ridx: 97, widx: 185453, cap: 185453)
at io.netty.buffer.AbstractByteBuf.checkReadableBytes0(AbstractByteBuf.java:1395)
at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1389)
at io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:850)
at io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:858)
at com.benberi.cadesim.client.codec.util.Packet.readBytes(Packet.java:79)
at com.benberi.cadesim.client.packet.in.ListAllMapsPacket.execute(ListAllMapsPacket.java:29)
Server Side:
Client-Side:
Server Packet:
@Override
public void encode() {
setPacketLengthType(PacketLength.MEDIUM); //
writeByte((byte)ServerConfiguration.getAvailableMaps().size());
for (int i=0; i<ServerConfiguration.getAvailableMaps().size(); i++)
{
String map = ServerConfiguration.getAvailableMaps().get(i).replace(".txt", "");
writeByteString(map);
String mapDir = String.format("maps/%s.png", map);
try {
File imageFile = new File(mapDir);
BufferedImage img = ImageIO.read(imageFile);
writeInt((int)imageFile.length()); //write size of image
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ImageIO.write(img, "png", stream);
writeBytes(stream.toByteArray()); // write image; byte array
stream.flush();
stream = null;
} catch (IOException e) {
// e.printStackTrace();
writeInt(0);
}
}
setLength(getBuffer().readableBytes());
}
Client Packet:
@Override
public void execute(Packet p) {
size = (int)p.readByte();
context.pixmapArray = new Pixmap[size]; //create Pixmap array with number of maps
int i=0;
while(i<size) {
context.getMaps().add((String)p.readByteString()); //writes all map names to list
Integer fileSize = p.readInt(); //read size of png
if(fileSize == 0) {//incase image not found from server
context.pixmapArray[i] = null;
}else {
Pixmap pixmap = new Pixmap(p.readBytes(fileSize), 0, fileSize); //byte[] to pixmap
context.pixmapArray[i] = pixmap; //add pixmap to pixmap array for future use
}
i++;
}
}
readBytes method:
public byte[] readBytes(int length) {
byte[] bytes = new byte[length];
this.dataBuffer.readBytes(bytes); //netty ByteBuf
return bytes;
}
Upvotes: 0
Views: 162
Reputation: 1633
Your issue is that you are re-encoding the image, and thus changing the file size. When you read the image ImageIO.read()
it may lose metadata, then when you write it with ImageIO.write()
it is not guaranteed to encode it byte for byte the exact same as it was initially encoded on disk. I'd recommend just copying the bytes directly from the file:
File imageFile = new File(mapDir);
byte[] fileContent = Files.readAllBytes(imageFile.toPath());
writeInt((int)imageFile.length()); //this should be the same as fileContent.length
writeBytes(fileContent);
Upvotes: 2