Netty - 心跳检测

Netty系列文章 - 心跳检测

本章暂且先不讨论Netty源码是怎么实现的,先看一下Netty心跳检测的应用.

科普基础

  1. 心跳机制
    • 心跳是在TCP长连接中,客户端和服务端定时向对方发送数据包通知对方自己还在线,保证连接的有效性的一种机制
    • 在服务器和客户端之间一定时间内没有数据交互时, 即处于 idle 状态时, 客户端或服务器会发送一个特殊的数据包给对方, 当接收方收到这个数据报文后, 也立即发送一个特殊的数据报文, 回应发送方, 此即一个 PING-PONG 交互. 自然地, 当某一端收到心跳消息后, 就知道了对方仍然在线, 这就确保 TCP 连接的有效性
  2. 心跳实现
    • 使用TCP协议层的Keeplive机制,但是该机制默认的心跳时间是2小时,依赖操作系统实现不够灵活
    • 应用层实现自定义心跳机制,比如Netty实现心跳机制

快速开始

Server

/**
 * @author Itachi is.xianglei@gmail.com
 * @Date 2020-01-03 15:56
 */
public class Server {
    @SneakyThrows
    public static void main(String[] args) {
        // 主线程
        EventLoopGroup master = new NioEventLoopGroup(1);
        // 工作线程
        EventLoopGroup slave = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(master,slave)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        pipeline.addLast(new StringDecoder(Charset.defaultCharset()));

                        pipeline.addLast(new DelimiterBasedFrameDecoder(4096, Delimiters.lineDelimiter()));

                        /**
                         * 10: 10秒后进入读空闲
                         * 15: 15秒后进入写空闲
                         * 30: 30秒后进入读写空闲
                         */
                        pipeline.addLast(new IdleStateHandler(10,15,30, TimeUnit.SECONDS));

                        /**
                         * 自定义的心跳检测处理器
                         */
                        pipeline.addLast(new HeartBeatHandler());

                        /**
                         * 自定义的消息处理器
                         */
                        pipeline.addLast(new MyHandler());
                    }
                });
        ChannelFuture channelFuture = bootstrap.bind("127.0.0.1", 9090).sync();
        channelFuture.channel().closeFuture();
    }

}

MyHandler

/**
 * @author Itachi is.xianglei@gmail.com
 * @Date 2020-01-03 16:06
 */
public class MyHandler extends SimpleChannelInboundHandler<String> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        Channel channel = ctx.channel();
        SocketAddress socketAddress = channel.remoteAddress();
        System.out.println(socketAddress + "->发来消息: "+msg);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        SocketAddress socketAddress = ctx.channel().remoteAddress();
        System.out.println(socketAddress+"<-已上线!");
    }
}

HeartBeatHandler

/**
 * @author Itachi is.xianglei@gmail.com
 * @Date 2020-01-03 16:32
 */
public class HeartBeatHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;

            // 读空闲
            if (IdleState.READER_IDLE == event.state()) {
                System.out.println("进入读空闲...");
            }

            // 写空闲
            if (IdleState.WRITER_IDLE == event.state()) {
                System.out.println("进入写空闲...");
            }

            // 读写空闲
            if (IdleState.ALL_IDLE == event.state()) {
                System.out.println("进入读写空闲,即将断开与客户端连接...");
                ctx.channel().close();
                System.out.println("断开连接!");
            }

        }
    }
}

客户端连接工具
在这里插入图片描述

推测: 在我们配置的读写时间内.我们客户端不往服务端发送数据,超过10秒,就会进入读空闲.

服务端不往客户端发送数据超过15秒就会进入写空闲, 在30秒内,不写不读的情况下…会一直进行心跳检测…

超过30秒后则会进入读写空闲,并关闭客户端的连接…

控制台输出
在这里插入图片描述

如有疑问,欢迎留言.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Netty 中,实现心跳检测可以使用 IdleStateHandler 类。这个类是一个 ChannelHandler,可以在一段时间内检测 Channel 是否有读或写事件发生,如果超时没有发生事件,就会触发一个 IdleStateEvent 事件。我们可以在 ChannelPipeline 中添加 IdleStateHandler,并在 ChannelInboundHandler 中处理 IdleStateEvent 事件。 以下是一个简单的示例代码: ```java public class HeartbeatServerInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); // 添加 IdleStateHandler,10 秒钟没有读事件,20 秒钟没有写事件,30 秒钟没有读写事件就会触发 IdleStateEvent 事件 pipeline.addLast(new IdleStateHandler(10, 20, 30, TimeUnit.SECONDS)); // 添加自定义的处理器,处理 IdleStateEvent 事件 pipeline.addLast(new HeartbeatServerHandler()); } } public class HeartbeatServerHandler extends ChannelInboundHandlerAdapter { @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleStateEvent e = (IdleStateEvent) evt; if (e.state() == IdleState.READER_IDLE) { // 10 秒钟没有读事件,可以认为客户端已经断开连接 ctx.close(); } else if (e.state() == IdleState.WRITER_IDLE) { // 20 秒钟没有写事件,发送心跳包 ctx.writeAndFlush(new HeartbeatMessage()); } else if (e.state() == IdleState.ALL_IDLE) { // 30 秒钟没有读写事件,可以认为客户端已经断开连接 ctx.close(); } } } } ``` 在上面的代码中,我们首先添加了一个 IdleStateHandler,指定了读超时时间、写超时时间和读写超时时间,然后添加了一个自定义的 ChannelInboundHandlerAdapter,重写了 userEventTriggered 方法,处理 IdleStateEvent 事件。在方法中,我们根据不同的 IdleState 处理不同的事件,例如读超时就关闭连接,写超时就发送心跳包。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值