Netty频道随机关闭

问题描述:

我的问题是,在几个频道连接到我的游戏的随机时间,将会导致所有频道关闭。 channelDisconnected方法被调用,并且我已经完成了这个事件的堆栈跟踪打印输出,并且一切似乎都正常。我的代码在下面;问题是什么?Netty频道随机关闭

public final class ServerChannelHandler extends SimpleChannelHandler { 

private static ChannelGroup channels; 
private static ServerBootstrap bootstrap; 

public static final void init() { 
    new ServerChannelHandler(); 
} 

/** 
* Gets the amount of channels that are currently connected to us 
* @return A {@code Integer} {@code Object} 
*/ 
public static int getConnectedChannelsSize() { 
    return channels == null ? 0 : channels.size(); 
} 

/** 
* Creates a new private constructor of this class 
*/ 
private ServerChannelHandler() { 
    channels = new DefaultChannelGroup(); 
    bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(CoresManager.serverBossChannelExecutor, CoresManager.serverWorkerChannelExecutor, CoresManager.serverWorkersCount)); 
    bootstrap.getPipeline().addLast("handler", this); 
    bootstrap.setOption("reuseAddress", true); // reuses adress for bind 
    bootstrap.setOption("child.tcpNoDelay", true); 
    bootstrap.setOption("child.TcpAckFrequency", true); 
    bootstrap.setOption("child.keepAlive", true); 
    bootstrap.bind(new InetSocketAddress(Constants.PORT_ID)); 
} 

/** 
* What happens when a new channel is open and connects to us 
*/ 
@Override 
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) { 
    channels.add(e.getChannel()); 
} 

/** 
* What happens when an open channel closes the connection with us 
*/ 
@Override 
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) { 
    channels.remove(e.getChannel()); 
} 

@Override 
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) { 
    ctx.setAttachment(new Session(e.getChannel())); 
} 

@Override 
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) { 
    Object sessionObject = ctx.getAttachment(); 
    if (sessionObject != null && sessionObject instanceof Session) { 
     Session session = (Session) sessionObject; 
     if (session.getDecoder() == null) 
      return; 
     if (session.getDecoder() instanceof WorldPacketsDecoder) { 
      session.getWorldPackets().getPlayer().finish(); 
     } 
    } 
} 

@Override 
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) { 
    if (!(e.getMessage() instanceof ChannelBuffer)) 
     return; 
    Object sessionObject = ctx.getAttachment(); 
    if (sessionObject != null && sessionObject instanceof Session) { 
     Session session = (Session) sessionObject; 
     if (session.getDecoder() == null) 
      return; 
     ChannelBuffer buf = (ChannelBuffer) e.getMessage(); 
     buf.markReaderIndex(); 
     int avail = buf.readableBytes(); 
     if (avail < 1 || avail > Constants.RECEIVE_DATA_LIMIT) { 
      return; 
     } 
     byte[] buffer = new byte[avail]; 
     buf.readBytes(buffer); 
     try { 
      session.getDecoder().decode(new InputStream(buffer)); 
     } catch (Throwable er) { 
      er.printStackTrace(); 
     } 
    } 
} 

@Override 
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent ee) throws Exception { 
    ee.getCause().printStackTrace(); 
} 

/** 
* On server shutdown, all channels are closed and the external resources 
* are released from the {{@link #bootstrap} 
*/ 
public static final void shutdown() { 
    channels.close().awaitUninterruptibly(); 
    bootstrap.releaseExternalResources(); 
} 

}

堆栈跟踪:

java.lang.Exception: Stack trace 
    at java.lang.Thread.dumpStack(Thread.java:1364) 
    at com.sallesy.game.player.Player.realFinish(Player.java:854) 
    at com.sallesy.game.player.Player.finish(Player.java:848) 
    at com.sallesy.game.player.Player.finish(Player.java:815) 
    at com.sallesy.networking.ServerChannelHandler.channelDisconnected(ServerChannelHandler.java:71) 
    at org.jboss.netty.channel.SimpleChannelHandler.handleUpstream(SimpleChannelHandler.java:120) 
    at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:558) 
    at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:553) 
    at org.jboss.netty.channel.Channels.fireChannelDisconnected(Channels.java:399) 
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.close(AbstractNioWorker.java:721) 
    at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleAcceptedSocket(NioServerSocketPipelineSink.java:111) 
    at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:66) 
    at org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendDownstream(DefaultChannelPipeline.java:774) 
    at org.jboss.netty.channel.SimpleChannelHandler.closeRequested(SimpleChannelHandler.java:338) 
    at org.jboss.netty.channel.SimpleChannelHandler.handleDownstream(SimpleChannelHandler.java:260) 
    at org.jboss.netty.channel.DefaultChannelPipeline.sendDownstream(DefaultChannelPipeline.java:585) 
    at org.jboss.netty.channel.DefaultChannelPipeline.sendDownstream(DefaultChannelPipeline.java:576) 
    at org.jboss.netty.channel.Channels.close(Channels.java:820) 
    at org.jboss.netty.channel.AbstractChannel.close(AbstractChannel.java:197) 
    at org.jboss.netty.channel.ChannelFutureListener$1.operationComplete(ChannelFutureListener.java:41) 
    at org.jboss.netty.channel.DefaultChannelFuture.notifyListener(DefaultChannelFuture.java:428) 
    at org.jboss.netty.channel.DefaultChannelFuture.addListener(DefaultChannelFuture.java:145) 
    at com.sallesy.networking.encoders.WorldPacketsEncoder.sendLogout(WorldPacketsEncoder.java:1179) 
    at com.sallesy.game.player.Player.logout(Player.java:801) 
    at com.sallesy.networking.decoders.handlers.ButtonHandler.handleButtons(ButtonHandler.java:227) 
    at com.sallesy.networking.decoders.WorldPacketsDecoder.processPackets(WorldPacketsDecoder.java:1122) 
    at com.sallesy.networking.decoders.WorldPacketsDecoder.decode(WorldPacketsDecoder.java:297) 
    at com.sallesy.networking.ServerChannelHandler.messageReceived(ServerChannelHandler.java:100) 
    at org.jboss.netty.channel.SimpleChannelHandler.handleUpstream(SimpleChannelHandler.java:88) 
    at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:558) 
    at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:553) 
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268) 
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255) 
    at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:84) 
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.processSelectedKeys(AbstractNioWorker.java:471) 
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:332) 
    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:35) 
    at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:102) 
    at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
    at java.lang.Thread.run(Thread.java:744) 

位猜测真正的,但可能是保活超时。 您可以尝试使用IdleStateHandler来保持连接活着。