netty版本
- netty版本:
io.netty:netty-all:4.1.33.Final
AttributeMap
-
AttributeMap
是绑定在Channel
或者ChannelHandlerContext
上的一个附件(在Netty4.1.X后ChannelHandlerContext.attr(xx) == Channel.attr(xx)
)。AttributeMap
是线程安全的。AttributeMap
必须是唯一的,因此最好定义成全局变量(比如static final类型) -
Channel
和ChannelHandlerContext
都扩展了AttributeMap接口,因此每一个Channel
和ChannelHandlerContext
实例都可以像Map一样按照key来存取value
代码案例
-
启动代码
public class EchoServer { private final int port; public EchoServer(int port) { this.port = port; } public void start() throws Exception { NioEventLoopGroup boss = new NioEventLoopGroup(1); NioEventLoopGroup worker = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(boss, worker) .channel(NioServerSocketChannel.class) .localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new LineBasedFrameDecoder(1024)); pipeline.addLast(new StringDecoder()); pipeline.addLast(new StringEncoder()); pipeline.addLast(new EchoServerHandlerA()); pipeline.addLast(new EchoServerHandlerB()); } }); ChannelFuture f = b.bind().sync(); System.out.println(String.format("%s started and listen on %s", EchoServer.class.getName(), f.channel().localAddress())); f.channel().closeFuture().sync(); } finally { boss.shutdownGracefully().sync(); worker.shutdownGracefully().sync(); } } public static void main(String[] args) throws Exception { new EchoServer(8080).start(); } }
-
EchoServerHandlerA
public class EchoServerHandlerA extends SimpleChannelInboundHandler<String> { private static final String LINE = System.getProperty("line.separator"); public static final AttributeKey<AtomicLong> CONNECT_COUNT = AttributeKey.valueOf("CONNECT_COUNT"); @Override public void channelActive(ChannelHandlerContext ctx) { Attribute<AtomicLong> attr = ctx.channel().attr(CONNECT_COUNT); AtomicLong count = attr.get(); if (count == null) { count = new AtomicLong(1); attr.setIfAbsent(count); System.out.println("A channelActive count is " + count.get()); } else { count.getAndIncrement(); System.out.println("A channelActive count is " + count.get()); } ctx.fireChannelActive(); } @Override public void channelRead0(ChannelHandlerContext ctx, String msg) { Attribute<AtomicLong> attr = ctx.channel().attr(CONNECT_COUNT); AtomicLong count = attr.get(); if (count == null) { count = new AtomicLong(1); attr.setIfAbsent(count); System.out.println("A channelRead count is " + count.get()); } else { count.getAndIncrement(); System.out.println("A channelRead count is " + count.get()); } ctx.fireChannelRead(msg); } }
-
EchoServerHandlerB
public class EchoServerHandlerB extends SimpleChannelInboundHandler<String> { private static final String LINE = System.getProperty("line.separator"); @Override public void channelActive(ChannelHandlerContext ctx) { Attribute<AtomicLong> attr = ctx.channel().attr(EchoServerHandlerA.CONNECT_COUNT); AtomicLong count = attr.get(); if (count == null) { count = new AtomicLong(1); attr.setIfAbsent(count); System.out.println("B channelActive count is " + count.get()); } else { count.getAndIncrement(); System.out.println("B channelActive count is " + count.get()); } ctx.fireChannelActive(); } @Override public void channelRead0(ChannelHandlerContext ctx, String msg) { Attribute<AtomicLong> attr = ctx.channel().attr(EchoServerHandlerA.CONNECT_COUNT); AtomicLong count = attr.get(); if (count == null) { count = new AtomicLong(1); attr.setIfAbsent(count); System.out.println("B channelRead count is " + count.get()); } else { count.getAndIncrement(); System.out.println("B channelRead count is " + count.get()); } } }
-
输出
A channelActive count is 1 B channelActive count is 2 A channelRead count is 3 B channelRead count is 4