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);
        }
    }
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。