Netty-心跳与空闲检测

  • 网络问题 

连接假死的现象是:在某一端(服务端或者客户端)看来,底层的 TCP 连接已经断开了,但是应用程序并没有捕获到,因此会认为这条连接仍然是存在的,从 TCP 层面来说,只有收到四次握手数据包或者一个 RST 数据包,连接的状态才表示已断开。

  •  空闲检测写法一:

服务端:只需要检测一段时间内,是否收到过客户端发来的数据即可,Netty 自带的 IdleStateHandler 就可以实现这个功能。

public class MyIdleStateHandler extends IdleStateHandler {
    public MyIdleStateHandler() {
        super(5, 0, 0, TimeUnit.SECONDS);
    }

    @Override
    protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception {
        System.out.println( "5秒内未读到数据,关闭连接");
        ctx.channel().close();
    }
}
  1. 其中第一个表示读空闲时间,指的是在这段时间内如果没有数据读到,就表示连接假死;第二个是写空闲时间,指的是 在这段时间如果没有写数据,就表示连接假死;第三个参数是读写空闲时间,表示在这段时间内如果没有产生数据读或者写,就表示连接假死。写空闲和读写空闲为0,表示我们不关心者两类条件;最后一个参数表示时间单位。
  2. 连接假死之后会回调 channelIdle() 方法,在这个方法里面打印消息,并手动关闭连接。

客户端:定时发心跳

public class HeartBeatTimerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //定时发送心跳包
        scheduleSendHeartBeat(ctx);

        super.channelActive(ctx);
    }
    private void scheduleSendHeartBeat(ChannelHandlerContext ctx) {
        ByteBuf byteBuf=ctx.alloc().buffer();
        byteBuf.writeByte(1);
        ctx.executor().schedule(() -> {
            if (ctx.channel().isActive()) {
                ctx.writeAndFlush(byteBuf);
                scheduleSendHeartBeat(ctx);
            }
        }, 2, TimeUnit.SECONDS);
    }
}

客户端空闲检测:只需要检测一段时间内,是否收到过服务端回复的数据即可,同服务器空闲检测(略)

服务端回复心跳:给客户端回复心跳(略)


  • 空闲检测写法二:

给连接加处理器:空闲检测处理器会调用下一个处理器的userEventTriggered()方法 

.childHandler(new ChannelInitializer<SocketChannel>() {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        //空闲检测,会调用下一个处理器的userEventTriggered()方法执行
        ch.pipeline().addLast(new IdleStateHandler(10,0,0));
        ch.pipeline().addLast(new MyPongWebSocketFrame());
    }
});

下一个处理器,重写userEventTriggered()方法

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import io.netty.handler.timeout.IdleStateEvent;

public class MyPongWebSocketFrame extends SimpleChannelInboundHandler<PongWebSocketFrame> {
    //用户事件触发的时候(如空闲检测)
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if(evt instanceof IdleStateEvent) {
            IdleStateEvent event= (IdleStateEvent) evt;
            System.out.println("MyPongWebSocketFrame userEventTriggered:" + event.state());
            ctx.channel().writeAndFlush(new PingWebSocketFrame());
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值