2013-07-11 36 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