Netty频道随机关闭

时间:2013-12-10 21:42:41

标签: java sockets networking netty channel

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

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)

1 个答案:

答案 0 :(得分:0)

有点猜测,但可能会保持超时。 您可以尝试使用IdleStateHandler来保持连接活动。