一、案例说明
- 编写一个 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();
}
}
}