2013-07-11 101 views
0

我的问题就像这样: “我特别感兴趣的是通道的另一端意外死亡的情况(例如,进程被终止)。不能可靠地触发通道关闭/断开连接事件,有时会发生并且有时不会发生,它也不一定会为连接重置抛出SocketException。无法在netty中检测到服务器端离线

但我的软件需要在任何可能的情况下保持连接,除非设备关机或网络断线。

我用netty连接了一个tcp设备。 设备作为tcp服务器端,tcp客户端通过netty写入。 我使用netty tcp-client从设备接收连续数据。 这个连接是一个长连接,永远不会平常。 现在,我怎么能检测到该设备是脱线与unexcept条件,如关机通过poweroff按钮或网线已断开。 netty的心跳不能正常工作。

cpLine.addLast("idleStateHandler", new IdleStateHandler(new HashedWheelTimer(), 5, 0, 0)); 
cpLine.addLast("heartbeatHandler", new HeartbeatHandler());. 

public void init() 
    { 
     factory = new NioClientSocketChannelFactory(MainFrame.THREAD_POOL, 
       MainFrame.THREAD_POOL); 
     bootstrap = new ClientBootstrap(factory); 
     bootstrap.setPipelineFactory(new ChannelPipelineFactory() 
     { 
      public ChannelPipeline getPipeline() throws Exception 
      { 
       ChannelPipeline cpLine = Channels.pipeline(); 
       cpLine.addLast("idleStateHandler", new IdleStateHandler(new HashedWheelTimer(), 5, 0, 0)); 
       cpLine.addLast("heartbeatHandler", new HeartbeatHandler()); 
       for (ChannelHandler handler : handlerList) 
       { 
        cpLine.addLast(handler.toString(), handler); 
       } 
       return cpLine; 
      } 
     }); 

     bootstrap.setOption("child.tcpNoDelay", true); 
     bootstrap.setOption("child.keepAlive", true); 
     bootstrap.setOption("writeBufferHighWaterMark", 100*1024*1024); 
     connect(); 
     Log.debug("TCPClient 初始化完成!"); 
    } 

我仍然无法设备侧离线检测。 当我得到idlestatus,我不能只是简单地关闭HeartbeatHandler中的频道。因为得到readidlestatus并不意味着设备已关闭,它可能没有数据传输。

这是HeartbeatHandler:

public class HeartbeatHandler extends IdleStateAwareChannelHandler { 

    Logger log=LogManager.getLogger(HeartbeatHandler.class); 
    @Override 
    public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) { 
     if (e.getState() == IdleState.READER_IDLE) { 
      log.info("Reader idle, closing channel"); 
      //e.getChannel().close(); 
      e.getChannel().write("heartbeat-reader_idle"); 
     } 
     else if (e.getState() == IdleState.WRITER_IDLE) { 
      log.info("Writer idle, sending heartbeat"); 
      e.getChannel().write("heartbeat-writer_idle"); 
     } 
     else if (e.getState() == IdleState.ALL_IDLE) { 
      log.info("All idle, sending heartbeat"); 
      e.getChannel().write("heartbeat-all_idle"); 
     } 
    } 
} 

回答

1

您将需要实施某种形式的心跳在你的协议层。你可以使用这个IdleStateHandler。

+0

我已经在tcp客户端使用'IdleStateHandler'和'HeartbeatHandler'类实现心跳。但tcp服务器端是一个设备。服务器端无法修改并且没有心跳。那么,我如何检测到设备处于脱机状态。感谢您的回答 – godith

+0

在'HeartbeatHandler'中,当我得到IdleState.READER_IDLE时,这个事件并不意味着设备已经脱机,它可能没有数据要传输,设备可能仍然在线。所以我不能只是简单地关闭频道,如果离线,我仍然不知道该设备 – godith