Netty 频道随机关闭
Posted
技术标签:
【中文标题】Netty 频道随机关闭【英文标题】:Netty Channels Randomly closing 【发布时间】:2013-12-28 15:26:51 【问题描述】:我的问题是,当多个频道连接到我的游戏时,会随机断开连接,导致所有频道都关闭。调用了 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】:确实有点猜测,但可能是keepalive超时。 您可以尝试使用 IdleStateHandler 来保持连接处于活动状态。
【讨论】:
以上是关于Netty 频道随机关闭的主要内容,如果未能解决你的问题,请参考以下文章