Netty中的session属性设置和链接事件捕获
Netty的使用比mina更灵活,也更复杂,下面通过一个例子,主要说明netty中如何对某个链接设置属性,并顺带描述了链接事件的捕获。
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.AttributeKey;
public class NettyAttrTest {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
private static final int IDEL_TIME_OUT = 10;
private static final int READ_IDEL_TIME_OUT = 4;
private static final int WRITE_IDEL_TIME_OUT = 5;
private AttributeKey<Long> START_TIME = new AttributeKey<Long>("START_TIME");
@Override
public void initChannel(SocketChannel ch) throws Exception {
//idle事件监听
ch.pipeline().addLast("idleStateHandler", new IdleStateHandler(READ_IDEL_TIME_OUT, WRITE_IDEL_TIME_OUT, IDEL_TIME_OUT));
ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
@Override
public void channelRegistered(ChannelHandlerContext ctx)//链接事件监听
throws Exception {
System.out.println("channel register");
//设置链接属性,记录链接开始的时间
ctx.attr(START_TIME).set(System.currentTimeMillis());
}
@Override
public void channelUnregistered(//断开链接事件
ChannelHandlerContext ctx) throws Exception {
System.out.println("channel unregister");
}
@Override
public void userEventTriggered(//事件监听
ChannelHandlerContext ctx, Object evt)
throws Exception {
//监听idle事件
if(IdleStateEvent.class.isAssignableFrom(evt.getClass())){
IdleStateEvent event = (IdleStateEvent) evt;
//获取链接相关的属性(即链接开始的时间戳)
Long startTime = ctx.attr(START_TIME).get();
if(startTime == null)
//not arrive forever
return;
//read idle
if(event.state() == IdleState.READER_IDLE)
System.out.println("read idle"+startTime);
//write idle
else if(event.state() == IdleState.WRITER_IDLE)
System.out.println("write idle"+startTime);
//read and write idle
else if(event.state() == IdleState.ALL_IDLE)
System.out.println("all idle"+startTime);
}
}
});
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = b.bind(8080).sync();
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
channelRegistered用于监听链接事件,当客户端链接时,将链接的时间记录在ctx的attr中。
userEventTriggered中针对某一个特定的链接取出其链接时间,并输出出来。
测试:开启两个telnet客户端:
telnet 127.0.0.1 8080
结果:
channel register
channel register
read idle1378195113609
write idle1378195113609
read idle1378195117015
read idle1378195113609
write idle1378195117015
all idle1378195113609
write idle1378195113609
read idle1378195117015
read idle1378195113609
all idle1378195117015
write idle1378195117015