banner
RustyNail

RustyNail

coder. 【blog】https://rustynail.me 【nostr】wss://ts.relays.world/ wss://relays.world/nostr

使用IdleStateHandler实现心跳机制

IdleStateHandler 简介#

IdleStateHandler 的本质上也是一个 channelhandler,也就是说可以把他加到 pipeline 里边。

IdleStateHandler 的作用就是在某些情况下的触发一个 IdleStateEvent。

某些情况:

在一段时间内

  • 没有读
  • 没有写
  • 没有读写

在触发 IdleStateEvent 之后就可以被下游的的 handler 接收到。

比如 10 秒没有读操作,发出一个READER_IDLE

ch.pipeline()
    .addLast(new IdleStateHandler(10, 0, 0, TimeUnit.SECONDS))
    .addLast(new HeartTrigger())
    }
});

位于下游的HeartTrigger就可以收到这个事件

public class HeartTrigger extends ChannelInboundHandlerAdapter {
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            // do something
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }
}

心跳#

心跳的模型很简单,客户端和服务端创建连接后,使用 IdleStateHandler 监听操作,
如果在一定的时间内没有* 操作,主动发送一个心跳包造成写操作。

客户端的操作对应着服务端的操作。也就是说客户端的心跳包或造成服务端的读操作。

而服务端监听 channel 的读操作,如过超时没有读操作,将关闭 channel(连接)。

而服务端的读监听时间间隔要比客户端的写监听时间间隔稍长一点,不然会因为略微的延迟而关闭 channel。

相关代码#

心跳包是自定义的数据结构,要考虑可能存在的半包 / 粘包问题

客户端发送心跳包

@Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            if (((IdleStateEvent) evt).state() == IdleState.WRITER_IDLE) {
                logger.info("发个心跳包告诉服务器自己没死。。");
                ctx.writeAndFlush(new TransData.Builder()
                        .type(TransData.TYPE_HT)
                        .build());
            }
        }
    }

服务端长时间没收到客户都的东西就关了 channel

@Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            if (((IdleStateEvent) evt).state() == IdleState.READER_IDLE) {
                logger.info("过久没收到客户端心跳,断开连接");
                ctx.close();
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }
加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。