为什么 ChannelGroup 频道的大小总是一。即使我连接更多的客户?
ChannelInitializer
因为每个新的Channel
(客户)都会调用child 。在那里您正在创建 的新实例ProcessingHandler
,因此每个频道都可以看到自己的ChannelGroup
.
解决方案 1 - 渠道属性
使用Attribute并将其与Channel
.
在某处创建属性(假设在Constants
类内):
public static final AttributeKey<ChannelGroup> CH_GRP_ATTR =
AttributeKey.valueOf(SomeClass.class.getName());
现在,创建将由所有实例使用的 ChannelGroup ProcessingHandler
:
final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
ChannelInitializer
在 NettyServer 中更新您的孩子:
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new RequestDecoder(),
new ResponseDataEncoder(),
new ProcessingHandler());
ch.attr(Constants.CH_GRP_ATTR).set(channels);
}
现在您可以像这样在处理程序中访问 ChannelGroup 的实例:
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
final ChannelGroup channels = ctx.channel().attr(Constants.CH_GRP_ATTR).get();
channels.add(ctx.channel());
这将起作用,因为每次新客户端连接时,都会使用相同的引用调用 ChannelInitializer ChannelGroup
。
解决方案 2 - 静态字段
如果您声明ChannelGroup
为静态,则所有类实例都将看到相同的ChannelGroup
实例:
private static final ChannelGroup channels =
new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
解决方案 3 - 传播共享实例
将参数引入构造函数ProcessingHandler
:
private final ChannelGroup channels;
public ProcessingHandler(ChannelGroup chg) {
this.channels = chg;
}
现在,在您的 NettyServer 类中创建实例ChannelGroup
并将其传播到 ProcessingHandler 构造函数:
final ChannelGroup channels = new
DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new RequestDecoder(),
new ResponseDataEncoder(),
new ProcessingHandler(channels)); // <- here
}
就个人而言,我会选择第一个解决方案,因为
- 它清楚地将 ChannelGroup 与 Channel 上下文相关联
- 您可以在其他处理程序中访问相同的 ChannelGroup
- 您可以拥有多个服务器实例(在同一 JVM 中的不同端口上运行)