这是我的服务器端代码。此代码借助netty读取udp流量。但是,有时候我有一个错误...。我无法修复...。
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
ByteBuf bb = msg.content();
RoomController roomController = RoomController.getInstance();
try
{
int opcode = bb.readUnsignedByte();
byte slot = bb.readByte();
byte[] ignore = new byte[8];
bb.readBytes(ignore);
int accountId = bb.readUnsignedByte();
switch(opcode)
{
case 65: {
log.info("Try connect player " + msg.sender().getAddress() + ":" + msg.sender().getPort());
Player player = roomController.getPlayer(msg.sender().getAddress());
if(player != null) {
ByteBuffer _buffer = new ByteBuffer();
_buffer.writeC((byte) 66);
_buffer.writeC((byte) 0);
_buffer.writeB(new byte[5]);
_buffer.writeC((byte) 0x0b);
_buffer.writeB(new byte[3]);
player.playerPort = msg.sender().getPort();
log.info("Send accept data! " + msg.sender().getAddress().toString() + ":" + msg.sender().getPort());
ctx.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(_buffer.getData(), 0, _buffer.getData().length), msg.sender()));
}
break;
}
//case (byte) 131:
//case (byte) 132:
//case 84:
//case 97:
case 131:
case 132:
case 4:
case 3: {
Player player = roomController.getPlayer(msg.sender().getAddress());
if(player != null) {
if(player.isActive) {
if(player.isHost) {
for(Player players : roomController.getPlayersForIP(player.roomID).values()) {
if(!players.isHost && players.playerPort > 0) {
ctx.writeAndFlush(new PBUDPServerPacket(opcode, Unpooled.copiedBuffer(msg.content()), new InetSocketAddress(players.playerIP, players.playerPort), (byte)slot, ignore, accountId).getPacket());
}
}
} else {
Player host = roomController.getHostForIP(player.roomID);
if(host.playerPort > 0) {
ctx.writeAndFlush(new PBUDPServerPacket(opcode, Unpooled.copiedBuffer(msg.content()), new InetSocketAddress(host.playerIP, host.playerPort), (byte)slot, ignore, accountId).getPacket());
}
}
}
}
break;
}
case 97: {
log.info("opcode: " + opcode + " sender: " + msg.sender().getAddress().getHostAddress());
ctx.writeAndFlush(new PBUDPServerPacket(opcode, Unpooled.copiedBuffer(msg.content()), new InetSocketAddress(msg.sender().getAddress(), msg.sender().getPort()), (byte)slot, ignore, accountId).getPacket());
break;
}
case 67: {
log.info("try remove player " + msg.sender().getAddress().toString());
RoomController.getInstance().removePlayer(msg.sender().getAddress());
break;
}
default: {
log.warn("unknown opcode: " + opcode);
}
}
}
catch(Exception e) {
log.error(e.toString());
}
finally {
bb.clear();
}
}
错误:
[18:16:46|ERROR|nioEventLoopGroup-2-1 |io.netty.util.ResourceLeakDetector ] LEAK: ByteBuf.release() was not called before it's garbage-collected.
如何解决错误?对我来说很重要。
堆栈跟踪:
[17:14:59|ERROR|nioEventLoopGroup-2-1 |io.netty.util.ResourceLeakDetector ] LEAK: ByteBuf.release() was not called before it's garbage-collected.
Recent access records: 1
#1:
io.netty.buffer.AdvancedLeakAwareByteBuf.writeBytes(AdvancedLeakAwareByteBuf.java:559)
io.netty.buffer.Unpooled.copiedBuffer(Unpooled.java:421)
ru.pb.battle.network.client.BattleClientConnection.channelRead0(BattleClientConnection.java:89)
ru.pb.battle.network.client.BattleClientConnection.channelRead0(BattleClientConnection.java:42)
io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:103)
io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338)
io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324)
io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785)
io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:93)
io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:485)
io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:452)
io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:346)
io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
java.lang.Thread.run(Thread.java:744)
Created at:
io.netty.util.ResourceLeakDetector.open(ResourceLeakDetector.java:190)
io.netty.buffer.AbstractByteBufAllocator.toLeakAwareBuffer(AbstractByteBufAllocator.java:42)
io.netty.buffer.UnpooledByteBufAllocator.newDirectBuffer(UnpooledByteBufAllocator.java:55)
io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:155)
io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:146)
io.netty.buffer.Unpooled.directBuffer(Unpooled.java:127)
io.netty.buffer.Unpooled.copiedBuffer(Unpooled.java:417)
ru.pb.battle.network.client.BattleClientConnection.channelRead0(BattleClientConnection.java:89)
ru.pb.battle.network.client.BattleClientConnection.channelRead0(BattleClientConnection.java:42)
io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:103)
io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338)
io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324)
io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785)
io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:93)
io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:485)
io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:452)
io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:346)
io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
java.lang.Thread.run(Thread.java:744)
====================== PBUDPServerPacket
public class PBUDPServerPacket {
private ByteBuf buff;
private InetSocketAddress addr;
public PBUDPServerPacket(int opcode, ByteBuf data, InetSocketAddress recipient, byte slot, byte[] ignore, int accountId) {
buff = Unpooled.buffer().order(ByteOrder.LITTLE_ENDIAN);
buff.writeByte(opcode);
buff.writeByte(slot);
buff.writeBytes(ignore);
buff.writeByte(accountId);
buff.writeBytes(data);
addr = recipient;
}
public DatagramPacket getPacket() {
return new DatagramPacket(buff, addr);
}
}
最佳答案
您需要在release
块中调用ByteBuf
而不是clear
上的finally
,否则引用计数的缓冲区将无法正确取消分配。