java - 通过数据包从服务器向客户端发送 png:indexOutOfBoundsException
问题描述
尝试从服务器向客户端发送 png 时,我使用 netty 得到一个 indexOutOfBoundException。错误发生在读取p.readBytes()
客户端字节的行上。
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)
服务器端:
- 获取服务器所在的特定文件夹中的图像
- 将图像转换为字节数组以发送数据
- 使用数据包向客户端发送数据
客户端:
- 接收图像的字节数组//我相信这里会出现问题
- 将字节数组转换为 Pixmap (libgdx)
- 将像素图添加到像素图数组的特定索引
- 稍后用 pixmap 做点什么
服务器数据包:
@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());
}
客户端数据包:
@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++;
}
}
读取字节方法:
public byte[] readBytes(int length) {
byte[] bytes = new byte[length];
this.dataBuffer.readBytes(bytes); //netty ByteBuf
return bytes;
}
解决方案
您的问题是您正在重新编码图像,从而更改文件大小。当您读取图像ImageIO.read()
时,它可能会丢失元数据,然后当您使用它编写它时ImageIO.write()
,不能保证对它进行逐字节编码,就像它最初在磁盘上编码一样。我建议直接从文件中复制字节:
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);
推荐阅读
- javascript - 如何在 swiper.js 中更改 swiper 的延迟?
- c# - VB Ctype 等价于 C#
- reactjs - Material UI Autocomplete - 选择项目后禁用列表框
- java - 找不到 SpringBoot bCryptPasswordEncoder bean
- python - 1970-01-01 00:00:00.000002000
- reactjs - Redux 设置状态
- php - 无法在php中更新数组的值
- node.js - 如果用户提及超过 5 人,则禁止用户
- firebase - 如何在 Firestore 中的 3 个单独的经过身份验证的用户之间共享数据?
- java - Lucene 如何在 StandardAnalyzer 中关闭“toLowerCase”?