content: package com.lgp.netty.netty_ch4;
  
  import io.netty.buffer.ByteBuf;
  import io.netty.buffer.Unpooled;
  import io.netty.channel.*;
  import io.netty.handler.timeout.IdleStateEvent;
  import io.netty.handler.timeout.IdleStateHandler;
  import io.netty.util.CharsetUtil;
  
  import java.util.concurrent.TimeUnit;
  
  /**
   * @AUTHOR lgp
   * @DATE 2018/12/29 15:11
   * @DESCRIPTION 空闲连接以及超时
   **/
  public class IdleStateHandlerInitializer extends ChannelInitializer<Channel> {
  
      @Override
      protected void initChannel(Channel ch) throws Exception {
          ChannelPipeline pipeline = ch.pipeline();
          //1 IdleStateHandler 将通过 IdleStateEvent 调用 userEventTriggered ，如果连接没有接收或发送数据超过60秒钟
          pipeline.addLast(new IdleStateHandler(0, 0, 60, TimeUnit.SECONDS));
          pipeline.addLast(new HeartbeatHandler());
      }
  
      public static final class HeartbeatHandler extends ChannelInboundHandlerAdapter {
          private static final ByteBuf HEARTBEAT_SEQUENCE =
                  //2 心跳发送到远端
                  Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("HEARTBEAT", CharsetUtil.ISO_8859_1));
  
          @Override
          public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
              if (evt instanceof IdleStateEvent) {
                  //3 发送的心跳并添加一个侦听器，如果发送操作失败将关闭连接
                  ctx.writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
              } else {
                  //4 事件不是一个 IdleStateEvent 的话，就将它传递给下一个处理程序
                  super.userEventTriggered(ctx, evt);
              }
          }
      }
  }
  