1 学习IdleStateHandler用来检测会话状态。
对于服务端,可以定时清除闲置会话。
对于客户端来说,检测会话是否断开,是否重连,用来检测网络延迟。
Netty3,触发的是handleUpstream方法:
// 设置管道工厂
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
//设置下线时间。第二个参数规定指定的秒数内没有读操作时将触发事件,第三个参数规定指定的秒数内没有写操作时将触发事件,
//均会触发ServerHandler-》中的handleUpstream
pipeline.addLast("idle", new IdleStateHandler(hashedWheelTimer, 5, 5, 10));
// 在此处设置后在messageReceived中将不需要转换
pipeline.addLast("decoder", new StringDecoder());
// 发送数据时不需要转换
pipeline.addLast("encoder", new StringEncoder());
// 业务处理对象
pipeline.addLast("helloHandler", new ServerHandler());
return pipeline;
}
});
public class ServerHandler extends SimpleChannelHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
System.out.println(e.getMessage());
}
@Override
public void handleUpstream(final ChannelHandlerContext ctx, ChannelEvent e)
throws Exception {
if (e instanceof IdleStateEvent) {
if(((IdleStateEvent)e).getState()==IdleState.ALL_IDLE){
//关闭会话,替玩家下线
ChannelFuture write=ctx.getChannel().write("time out,you will close");
write.addListener(new ChannelFutureListener() {
/**
* IO操作执行完回调
*/
public void operationComplete(ChannelFuture future) throws Exception {
// TODO Auto-generated method stub
ctx.getChannel().close();
}
});
System.out.println("替玩家下线。。。");
ctx.getChannel().close();
}
IdleStateEvent event = (IdleStateEvent) e;
System.out.println(event.getState()+" ");
} else {
super.handleUpstream(ctx, e);
}
}
}
Netty5,触发的是userEventTriggered方法:
// 设置管道工厂
bootstrap.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new IdleStateHandler(5, 5, 10));
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new ServerHandler());
}
});
触发的事件
/**
* 服务端消息处理
*
* @author Tang
*
*/
public class ServerHandler extends SimpleChannelInboundHandler<String> {
@Override
public void userEventTriggered(final ChannelHandlerContext ctx, Object evt)
throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state() == IdleState.ALL_IDLE) {
// 向客户端发送数据
ChannelFuture writeAndFlush = ctx
.writeAndFlush("you will close");
writeAndFlush
.addListener(new GenericFutureListener<Future<? super Void>>() {
public void operationComplete(
Future<? super Void> future)
throws Exception {
// 关闭会话
ctx.channel().close();
}
});
}
}
}
通过设置时间,当一个连接超过这个时间没有连接时将触发userEventTriggered方法。