心跳检测
服务侧可使用Netty中提供IdleStateHandler类来检测客户端的心跳,服务端只需在IdleStateHandler之后的ChannelInboundHandler重写心跳超时所触发的userEventTriggered事件方法即可。
添加IdleStateHandler和ServerHeartbeatHandler
ch.pipeline().addLast(new IdleStateHandler(3, 0 ,0)); ch.pipeline().addLast(new ServerHeartbeatHandler());
心跳检测方法
public class ServerHeartbeatHandler extends ChannelInboundHandlerAdapter {
private int readerIdleCount = 0;
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
IdleStateEvent stateEvent = (IdleStateEvent) evt;
if (IdleState.READER_IDLE.equals(stateEvent.state())) {
readerIdleCount++;
System.out.println("超时一次");
}
if (3 < readerIdleCount) {
// 通知客户端关闭连接
ctx.channel().writeAndFlush("close");
ctx.channel().close();
System.out.println("释放客户端连接");
}
}
} 心跳检测源码
IdleStateHandler继承自ChannelInboundHandlerAdapter类,也属于ChannelInboundHandler,所以在客户端连接服务端的时候,会执行channelActive方法
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
initialize(ctx);
super.channelActive(ctx);
}
private void initialize(ChannelHandlerContext ctx) {
//...
if (readerIdleTimeNanos > 0) {
// 生成周期任务
readerIdleTimeout = schedule(ctx, new ReaderIdleTimeoutTask(ctx),
readerIdleTimeNanos, TimeUnit.NANOSECONDS);
}
//...
}
private final class ReaderIdleTimeoutTask extends AbstractIdleTask {
@Override
protected void run(ChannelHandlerContext ctx) {
long nextDelay = readerIdleTimeNanos;
if (!reading) {
nextDelay -= ticksInNanos() - lastReadTime;
}
// 周期内未收到客户端请求
if (nextDelay <= 0) {
// 重新生成周期任务
readerIdleTimeout = schedule(ctx, this, readerIdleTimeNanos, TimeUnit.NANOSECONDS);
boolean first = firstReaderIdleEvent;
firstReaderIdleEvent = false;
try {
// 读空闲事件
IdleStateEvent event = newIdleStateEvent(IdleState.READER_IDLE, first);
// 触发下一个ChannelInboundHandler的userEventTriggered方法
channelIdle(ctx, event);
} catch (Throwable t) {
ctx.fireExceptionCaught(t);
}
}
}
} 
京公网安备 11010502036488号