我的问题是这样的:“特别是我对通道的另一端意外死亡(例如进程被杀死)的情况感兴趣。似乎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");
}
}
}