0

我的问题是这样的:“特别是我对通道的另一端意外死亡(例如进程被杀死)的情况感兴趣。似乎netty不能可靠地触发通道关闭/断开事件,有时它确实和有时它不会。它也不一定会抛出 SocketException 来重置连接。”

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

我用netty连接了一个tcp设备。设备作为 tcp 服务器端,tcp 客户端由 netty 编写。我使用 netty tcp-client 从设备接收连续数据。这个连接是一个长连接,通常永远不会被关闭。现在,我怎么能检测到设备在无异常情况下离线,比如通过关机按钮关机或网线断了。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 初始化完成!");
    }

我仍然无法检测到设备端离线。当我得到空闲状态时,我不能简单地关闭 HeartbeatHandler 中的通道。因为获取 readidlestatus 并不意味着设备已关闭,它可能没有数据要传输。

这是心跳处理器:

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");
        }
    }
}
4

1 回答 1

1

您将需要在协议层中实现某种心跳。您可以为此使用 IdleStateHandler。

于 2013-07-12T19:26:24.823 回答