[英]Netty ChannelGroup over ConcurrentHashMap
我正在开发一款基于netty的多人游戏服务器。 传输到客户端的大多数消息都是特定于单个客户端的,但有时我需要向所有客户端广播相同的消息。
我不确定是否有充分的理由在我自己的Map上使用ChannelGroup。 所以现在我有:
public class GameSession {
/* a map of all the players part of this game session */
private ConcurrentHashMap<String, PlayerHandler> players = new ConcurrentHashMap<String, PlayerHandler>();
private final ChannelGroup playersChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
PlayerHandler在哪里:
public class PlayerHandler extends SimpleChannelInboundHandler<IncomingMessage>
并包含有状态成员变量。
当一个新玩家加入时(在完成一些逻辑之后),他将被添加到GameSession中:
public void addPlayer(PlayerHandler p) {
if (p.getGameSessionID().equals(this.gameId)) {
players.put(p.getPlayerID(), p); //add this player to our game session
playersChannels.add(p.getChannelFromCtx()); //get channel and add to ChannelGroup
}
}
假设玩家要求离开(或关闭连接),我想播放一条消息
public void notifyPlayerLeft(String exPlayer) {
//Broadcast message with the id of the player that left
for (Map.Entry<String, PlayerHandler> entry : players.entrySet()) {
PlayerHandler player = entry.getValue();
player.sendPlayerLeft(exPlayer);
}
}
其中sendPlayerLeft()是一个简单的方法,它可以执行以下操作:
ctx.writeAndFlush(outgoingMsg)
如果我使用ChannelGroup,我可以这样做:
playersChannels.writeAndFlush(outgoingMsg, matcher)
但我不确定为什么这是一个更好的主意。 Netty表示它是异步发生的但是由于PlayerHandler没有自己的线程,不会像我在NotifyPlayerLeft()中那样迭代对象也会异步吗? 请注意,整个场景将由一个频道/用户/线程触发。
我希望我的问题足够清楚。 谢谢!
正如您在此处所看到的,Netty对组的默认写入再次是一个简单的迭代。 从这个意义上讲,您的方法在性能和并发性方面应该没有区别。 主要区别在于它将所有期货收集到地图中,这种分组可以帮助您跟踪引发的任何问题。 但是,为什么要使用你的代码已经实现了?
用信息更新它。 因此,虽然ChannelGroup
对于前面所述的简单迭代很有用,但您也可以从API文档中获益。
Netty.io 4.1 ChannelGroup API文档
关闭的频道会自动从集合中删除,因此您无需担心添加的频道的生命周期。 频道可以属于多个频道组。
您可以通过扩展DefaultChannelGroup.class
来创建新的ChannelGroup.class
,并添加一些方法以在通道注销期间添加其他行为,以通知某些代码未注册Channel,然后通知其他玩家,或者进行清理。
小心Netty的ConcurrentHashMap; 它实际上是马车; 它不是线程安全的。 您可以在放置另一个线程时在一个线程上使用并发流来验证此错误。 它并不总是失败,因为它与非原子内部数组突变有关(快节奏并发r / w应该与netty但不是jdk失败。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.