天天看点

使用netty实现心跳检查

项目背景:

硬件设备和服务器websocket长连接通讯

使用技术:

java/netty

心跳频率和关闭时长:

看设备接入数和业务要求,比如6秒一个心跳包,对方收到后也返回一个心跳响应。双方2.5个周期内没收到数据则关闭各自链接。常用心跳周期如2s,4s,6s,8s,10s...

哪个来发:

根据我们业务,服务器端来主动发心跳包。开始心跳周期可以设置长点,比如10s。如果业务需求心跳检查要迅速,则修改服务器端的心跳周期,设备固件升级。对于未升级的设备在一个关闭时长内可能会收到2个以上心跳包,不受影响。

代码实现:

READ_IDEL_TIME_OUT=25s

WRITE_IDEL_TIME_OUT=15s

ALL_IDEL_TIME_OUT=10s

HEARTBEAT_REQUEST=“H”

HEARTBEAT_RESPONSE=“B”

 inboundHandler继承的是SimpleChannelInboundHandler<TextWebSocketFrame> 类。

服务器端:

step1.  pipeline初始化配置

pipeline.addLast(new IdleStateHandler(READ_IDEL_TIME_OUT,WRITE_IDEL_TIME_OUT, ALL_IDEL_TIME_OUT, TimeUnit.SECONDS));

step2.  在任何一个handler里实现userEventTriggered方法

    @Override  

    public void userEventTriggered(ChannelHandlerContext ctx, Object evt)  

            throws Exception {  

        if (evt instanceof IdleStateEvent) {  

            IdleStateEvent event = (IdleStateEvent) evt;  

            if (event.state().equals(IdleState.READER_IDLE)) {  

                //未进行读操作  

                log.error("READER_IDLE");  

                // 超时关闭channel  

                ctx.close();  

            } else if (event.state().equals(IdleState.WRITER_IDLE)) {  

                //log.error("WRITER_IDLE"); 

            } else if (event.state().equals(IdleState.ALL_IDLE)) {  

                //未进行读写  

                log.info("SEND HeartBeat:H"); 

                ctx.channel().writeAndFlush(new TextWebSocketFrame(HEARTBEAT_REQUEST));                

            }  

        }  

    } 

服务器端:

step1.  pipeline初始化配置

pipeline.addLast(new IdleStateHandler(READ_IDEL_TIME_OUT,WRITE_IDEL_TIME_OUT, ALL_IDEL_TIME_OUT, TimeUnit.SECONDS));

step2.  在任何一个handler里实现userEventTriggered方法

    @Override  

    public void userEventTriggered(ChannelHandlerContext ctx, Object evt)  

            throws Exception {  

        if (evt instanceof IdleStateEvent) {  

            IdleStateEvent event = (IdleStateEvent) evt;  

            if (event.state().equals(IdleState.READER_IDLE)) {  

                //未进行读操作  

                log.error("READER_IDLE");  

                // 超时关闭channel  

                ctx.close();  

            } else if (event.state().equals(IdleState.WRITER_IDLE)) {  

                //log.error("WRITER_IDLE"); 

            } else if (event.state().equals(IdleState.ALL_IDLE)) {  

                //未进行读写             

            }  

        }  

    } 

step3.收到服务器心跳后,响应

    @Override

    protected void channelRead0(ChannelHandlerContext arg0, TextWebSocketFrame arg1) throws Exception {

        // TODO Auto-generated method stub

        String txt=arg1.text();

        log.info("RECV:"+arg1.text());

        if (HEARTBEAT_REQUEST.equals(txt)){

            arg0.channel().writeAndFlush(new TextWebSocketFrame(HEARTBEAT_RESPONSE) ).sync();

            log.info("SEND:"+HEARTBEAT_RESPONSE);

        }

    }