这里的超时指的是idle状态,分为三类:读超时,写超时,所有超时(读或者写)
IdleStateHandler,通过pipeline添加
pipeline.addLast(new IdleStateHandler(READ_IDEL_TIME_OUT,
WRITE_IDEL_TIME_OUT, ALL_IDEL_TIME_OUT, TimeUnit.SECONDS));
如果有事件,触发userEventTriggered方法。
代码
//HeartBeatServer.java package com.waylau.netty.demo.heartbeat; 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; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; /** * 说明:心跳服务器 * * @author <a href="http://www.waylau.com">waylau.com</a> 2015年11月6日 */ public final class HeartbeatServer { static final int PORT = 8082; public static void main(String[] args) throws Exception { // Configure the server. EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 100) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new HeartbeatHandlerInitializer()); // Start the server. ChannelFuture f = b.bind(PORT).sync(); // Wait until the server socket is closed. f.channel().closeFuture().sync(); } finally { // Shut down all event loops to terminate all threads. bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } } //HeartBeatHandlerInitializer.java package com.waylau.netty.demo.heartbeat; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.handler.timeout.IdleStateHandler; import java.util.concurrent.TimeUnit; /** * 说明:心跳服务器初始化 * * @author <a href="http://www.waylau.com">waylau.com</a> 2015年11月6日 */ public class HeartbeatHandlerInitializer extends ChannelInitializer<Channel> { private static final int READ_IDEL_TIME_OUT = 6; // 读超时 private static final int WRITE_IDEL_TIME_OUT = 4;// 写超时 private static final int ALL_IDEL_TIME_OUT = 0; // 所有超时 @Override protected void initChannel(Channel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new IdleStateHandler(READ_IDEL_TIME_OUT, WRITE_IDEL_TIME_OUT, ALL_IDEL_TIME_OUT, TimeUnit.SECONDS)); pipeline.addLast(new HeartbeatServerHandler()); } } //HeartBeatServerHandler.java package com.waylau.netty.demo.heartbeat; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; import io.netty.util.CharsetUtil; /** * 说明:心跳服务器处理器 * * @author <a href="http://www.waylau.com">waylau.com</a> 2015年11月6日 */ public class HeartbeatServerHandler extends ChannelInboundHandlerAdapter { // Return a unreleasable view on the given ByteBuf // which will just ignore release and retain calls. private static final ByteBuf HEARTBEAT_SEQUENCE = Unpooled .unreleasableBuffer(Unpooled.copiedBuffer("Heartbeat", CharsetUtil.UTF_8)); @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleStateEvent event = (IdleStateEvent) evt; String type = ""; if (event.state() == IdleState.READER_IDLE) { type = "read idle"; } else if (event.state() == IdleState.WRITER_IDLE) { type = "write idle"; } else if (event.state() == IdleState.ALL_IDLE) { type = "all idle"; } ctx.writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()).addListener( ChannelFutureListener.CLOSE_ON_FAILURE); System.out.println( ctx.channel().remoteAddress()+"超时类型:" + type); } else { super.userEventTriggered(ctx, evt); } } }