一、何为心跳
顾名思义, 所谓 心跳, 即在 TCP 长连接中, 客户端和服务器之间定期发送的一种特殊的数据包, 通知对方自己还在线, 以确保 TCP 连接的有效性.
二、为什么需要心跳
因为网络的不可靠性, 有可能在 TCP 保持长连接的过程中, 由于某些突发情况, 例如网线被拔出, 突然掉电等, 会造成服务器和客户端的连接中断. 在这些突发情况下, 如果恰好服务器和客户端之间没有交互的话, 那么它们是不能在短时间内发现对方已经掉线的. 为了解决这个问题, 我们就需要引入 心跳 机制. 心跳机制的工作原理是: 在服务器和客户端之间一定时间内没有数据交互时, 即处于 idle 状态时, 客户端或服务器会发送一个特殊的数据包给对方, 当接收方收到这个数据报文后, 也立即发送一个特殊的数据报文, 回应发送方, 此即一个 PING-PONG 交互. 自然地, 当某一端收到心跳消息后, 就知道了对方仍然在线, 这就确保 TCP 连接的有效性.
三、心跳实现使用TCP协议层的Keeplive机制,但是该机制默认的心跳时间是2小时,依赖操作系统实现不够灵活;
心跳机制一般来说都是在逻辑层发送空的包来实现的,比如Netty的IdleStateHandler类实现心跳机制。
心跳机制实现逻辑:每隔几分钟发送一个固定信息给服务端,服务端收到后回复一个固定信息给客户端,如果服务端几分钟内没有收到客户端信息则视客户端断开。
在Netty中IdleStateHandler主要用来检测远端是否存活,如果不存活或活跃则对空闲Socket连接进行处理避免资源的浪费;IdleStateHandler实现对三种心跳的检测,分别是readerIdleTime、writerIdleTime和allIdleTime,参数解释如下: 1)readerIdleTime:读超时时间2)writerIdleTime:写超时时间3)allIdleTime:所有类型的超时时间
所以在channelPipeline中加入IdleStateHandler,我们在handler中提示的是5秒读,所以我们服务端的配置的是:
ph.addLast(new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS));
因为服务端必须5秒接受一次心跳请求,那么客户端的配置:
ph.addLast( new IdleStateHandler(0, 4, 0, TimeUnit.SECONDS));
userEventTriggered是Netty 处理心跳超时事件,在IdleStateHandler设置超时时间,如果达到了,就会直接调用该方法。如果没有超时则不调用。我们重写该方法的话,就可以自行进行相关的业务逻辑处理了。
四、IdleStateHandler心跳检测实例a、服务端HeartNettyServer——服务端启动类
package com.dxfx.netty.demo;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelOption;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioServerSocketChannel;/**
* 服务端启动类
*
* @author Administrator
**/public class HeartNettyServer {
public static void main(String[] args) throws InterruptedException {
// 首先,netty通过ServerBootstrap启动服务端
ServerBootstrap server = new ServerBootstrap();
EventLoopGroup parentGroup