0
votes

my question just like this: "specifically i am interested in the case where the other end of the channel dies unexpectedly (eg the process gets killed). it seems that netty does not reliably fire a channel closed/disconnect event, sometimes it does and sometimes it does not. it also does not necessarily throw a SocketException for connection reset."

but my software need to keep connected at any possible conditon,unless device shutdown or net wire break.

i connect a tcp device with netty. device as tcp server-side,tcp client-side write by netty. i use netty tcp-client to receive continus data from device. this connect is a long connect ,never be colsed on usual. now,how i could detect the device is offline with unexcept conditions,like shutdown by poweroff button or net wire has broken. the heartbeat of netty can not work well .

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 初始化完成!");
    }

i still can't detect device-side offline. when i get the idlestatus ,i can't just simply close the channel in HeartbeatHandler.because get readidlestatus not means the device has shutdown,it could be has no data to trasfer.

this is the 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

1 Answers

1
votes

You will need to implement some kind of heartbeat in your protocol layer. You can make use of the IdleStateHandler for this.