代码以及分析
虽然handler中有连接断开然后会执行的方法处理,但是有些特殊情况会使连接断开但是服务器并没有感知到,所有加入心跳检测机制可以保证连接的稳定性
Server
public class MyServer {
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
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
/*
IdleStateHandler是netty提供的处理空闲状态的处理器
参数:
long readerIdleTime:表示多长时间没有读,发送心跳检测包,检测是否还处于连接状态
long writerIdleTime:表示多长时间没有写,发送心跳检测包,检测是否还处于连接状态
long allIdleTime:表示多长时间既没有读,也没有写,发送心跳检测包,检测是否还处于连接状态
当IdleStateHandler触发后,就会传递给管道的下一个handler去处理
通道调用下一个handler的userEventTriggered方法
*/
pipeline.addLast(new IdleStateHandler(3, 5, 7, TimeUnit.SECONDS));
//加入对空闲检测进一步处理的handler
pipeline.addLast(new ServerHandler());
}
});
ChannelFuture channelFuture = serverBootstrap.bind(7000).sync();
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
Handler
public class ServerHandler extends ChannelInboundHandlerAdapter {
/**
* @param ctx 上下文
* @param evt 事件
* @throws Exception
*/
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
String eventType = "";
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("服务器做出相应的处理");
}
}
}