在Netty中,会定期发送一个数据包,也就是“心跳”,来确定客户端和服务端是否连接。该机制通过IdleStateHandler处理器和自定义的handler的userEventTriggered方法来实现,具体的实例如下图:
Server:
public class Server {
public static void main(String[] args) throws InterruptedException {
//创建两个线程组
EventLoopGroup boss=new NioEventLoopGroup(1);
EventLoopGroup worker=new NioEventLoopGroup();
try{
ServerBootstrap bootstrap=new ServerBootstrap()
.group(boss,worker)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
//给bossgruop添加一个日志处理器
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//加入netty提供的 IdLeStateHandler
//处理空闲状态的处理器
//三个参数:1.表示多久没有读 会发送一个心跳检测包检测是否链接
//2.表示多久没有写 会发送一个心跳检测包检测是否链接 3.多长时间没有读写 会发送一个心跳检测包检测是否链接
//当IdLeStateEvent触发后 会传递给下一个handler处理
//通过调用下一个handler的userEventTiggered 在该方法中处理
pipeline.addLast(new IdleStateHandler(3,5,7, TimeUnit.SECONDS));
//加入对一个空闲检测进行进一步处理的handler
pipeline.addLast(new ServerHandler());
}
});
//启动服务器
ChannelFuture channelFuture = bootstrap.bind(8848).sync();
channelFuture.channel().closeFuture().sync();
}
finally {
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
}
ServerHandler:
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 idleStateEvent = (IdleStateEvent) evt;
String eventType = null;
switch (idleStateEvent.state()) {
case READER_IDLE:
eventType = "读空闲";
break;
case WRITER_IDLE:
eventType = "写空闲";
break;
case ALL_IDLE:
eventType = "读写空闲";
break;
}
System.out.println(ctx.channel().remoteAddress() + eventType);
//如果空闲发生 关闭通道
ctx.channel().close();
}
}
}