iohao / ioGame

无锁异步化、事件驱动架构设计的 java netty 网络编程框架; 轻量级,无需依赖任何第三方中间件或数据库就能支持集群、分布式; 适用于网络游戏服务器、物联网、内部系统及各种需要长连接的场景; 通过 ioGame 你可以很容易的搭建出一个集群无中心节点、集群自动化、分布式的网络服务器;FXGL、Unity、UE、Cocos Creator、Godot、Netty、Protobuf、webSocket、tcp、socket;java Netty 游戏服务器框架; Java Netty Game Server.
http://game.iohao.com
GNU Affero General Public License v3.0
920 stars 205 forks source link

顶号操作疑似bug #334

Closed xujiaw closed 4 months ago

xujiaw commented 4 months ago
   ExternalCommunicationKit.forcedOffline(userId);
    boolean success = UserIdSettingKit.settingUserId(flowContext, userId);

按示例文档提示, 第一行代码是关闭现在已连接用户通道, 再绑定现有的连接, 但是看源码, 第一步是走的异步, 那第一步和第二步如果并发冲突后, 会不会第一步的杀通道, 把自己当前连接干掉

iohao commented 4 months ago

forcedOffline、settingUserId 方法都是同步调用。

xujiaw commented 4 months ago

调用方是同步,但是看执行方,也就是对外服是异步的

xujiaw commented 4 months ago

@Override public void removeUserSession(long userId, Object msg) { this.ifPresent(userId, userSession -> { ChannelFuture channelFuture = userSession.writeAndFlush(msg); channelFuture.addListener((ChannelFutureListener) future -> { // 回调 UserSessions 中移除对应的玩家 this.removeUserSession(userSession); }); }); }

这个是对外服删除会话的代码,会在删除前刷新最后一条消息, 并走了监听成功再开始删
iohao commented 4 months ago

这的确是有概率触发并发问题,如下述代码可能会将新添加的移除,从而引发问题。

https://github.com/iohao/ioGame/blob/026519718dd9f1d7c330610ceabdd53be96b08ba/external/external-netty/src/main/java/com/iohao/game/external/core/netty/session/SocketUserSessions.java#L132-L134

iohao commented 4 months ago

已修复,请使用 dev 分支尝试

https://github.com/iohao/ioGame/blob/261f472d992313787b9b25a9baba1cc7ccf98328/external/external-netty/src/main/java/com/iohao/game/external/core/netty/session/SocketUserSessions.java#L132-L135

xujiaw commented 4 months ago

好的,我试下, 现在的问题就是客户端持有的socket与服务端对应的socket不是同一个

xujiaw commented 4 months ago

那还有没有这样的并发问题, 就是客户端两个socket同时连过来, 那么在第一步代码ExternalCommunicationKit.forcedOffline(userId);删除历史绑定时, 谁也没删除谁, 然后到第二步绑定的时候, 是不是就是看运气谁能绑定上了?