一、案例说明
- 编写一个 Netty 心跳检测机制案例,当服务器超过 3 秒没有读时,就提示读空闲
- 当服务器超过 5 秒没有写操作时,就提示写空闲
- 实现当服务器超过 7 秒没有读或者写操作时,就提示读写空闲
- 代码如下:
二、代码示例
MyServer
public class MyServer { public static void main(String[] args) throws InterruptedException { // 创建两个线程 NioEventLoopGroup bossGroup = new NioEventLoopGroup(); NioEventLoopGroup workerGroup = new NioEventLoopGroup(3); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO))// 在 bossGroup 增加一个日志处理器 .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); /** * 加入一个 netty 提供 IdleStateHandler * 1、IdleStateHandler 是 netty 提供的处理空闲状态的处理器 * 2、Long readerIdleTime:表示多长时间没有读,就会发送一个心跳检测包,检测是否还是连接的状态 * 3、Long writerIdleTime:表示多长时间没有写操作,就会发送一个心跳检测包,检测是否还是连接的状态 * 4、Long allIdleTime:表示多长时间即没有读也没有写操作,就会发送一个心跳检测包,检测是否还是连接的状态 * * 文档说明: * Triggers an IdleStateEvent when a Channel has not performed read, write, or both operation for a while. * * 5、当 IdleStateEvent 触发后,就会传递给管道的下一个handler去处理,通过调用下一个handler 的 userEventTriggered ,在该方法中去处理 * IdleStateEvent(读空闲,写空闲,读写空闲) */ pipeline.addLast(new IdleStateHandler(3, 5, 7, TimeUnit.SECONDS)); // 加入一个对空闲检测进一步处理的 handler (自定义) pipeline.addLast(new MyServerHandler()); } }); // 启动服务器 ChannelFuture channelFuture = serverBootstrap.bind(6699).sync(); channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }}
MyServerHandler
public class MyServerHandler extends ChannelInboundHandlerAdapter { /** * @param ctx 上下文 * @param evt 事件 * @throws Exception */ @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { // 将 evt 向下转型 IdleStateEvent IdleStateEvent event = (IdleStateEvent) evt; String eventType = null; switch (event.state()) { case READER_IDLE: eventType = "读空闲"; break; case WRITER_IDLE: eventType = "写空闲"; break; case ALL_IDLE: eventType = "读写空闲"; break; } System.out.println(ctx.channel().remoteAddress() + "--超时时间--" + eventType); System.out.println("服务器做相应处理。。。。。"); // 如果发生空闲,我们关闭通道 ctx.channel().close(); } }}