iohao / ioGame

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

Home Page:http://game.iohao.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

关于广播客户端监听的问题

MengLiuLei opened this issue · comments

我今天看了一天的文档,然后我们的业务逻辑大致是类似于,一个用户登陆,其他用户要能够知道所有用户的登陆,然后@ActionMethod的方法需要使用void广播的形式来给所有登陆成功用户的users发送相同的数组列表。然后我自己写了一个demo的method。
服务端代码:

 @ActionMethod(DemoCmdForSpring.login)
    public void login(DemoUserInfo userInfo, FlowContext flowContext) {
        DemoUserInfo newUserInfo = new DemoUserInfo();
        String phone =  userInfo.phone;
        long id = Long.parseLong(phone);
        UserIdSettingKit.settingUserId(flowContext,id);
        longs.add(id);
        BroadcastContext broadcastContext = BrokerClientHelper.getBroadcastContext();
        newUserInfo.phone = "链接成功,当前有用户:" + JSONArray.toJSONString(longs);
        CmdInfo cmdInfo = CmdInfo.of(DemoCmdForSpring.cmd, DemoCmdForSpring.login);
        broadcastContext.broadcast(cmdInfo,newUserInfo,longs);
    }

然后使用InternalRegion1 来监听:

static class InternalRegion1 extends AbstractInputCommandRegion {
       @Override
       public void initInputCommand() {
           inputCommandCreate.cmd = DemoCmdForSpring.cmd;
           ofListen(result -> {
               DemoUserInfovalue = result.getValue(DemoUserInfo.class);
               log.info("broadcastMessage ========== \n{}", value);
           }, DemoCmdForSpring.login, "login");
       }
   }

使用LoginOne来进行发送消息:

static class LoginOne extends AbstractInputCommandRegion {
        @Override
        public void initInputCommand() {
            inputCommandCreate.cmd = DemoCmdForSpring.cmd;
            ofCommand(DemoCmdForSpring.login).setTitle("login").setRequestData(() -> {
                DemoUserInfo userInfo = new DemoUserInfo();
                userInfo.setPhone("1");
                return userInfo;
            }).callback(result -> {
                DemoCmdForSpring value = result.getValue(DemoCmdForSpring.class);
                log.info("value : {}", value);
            });
            // 一秒后,执行模拟请求;
            TaskKit.runOnceSecond(() -> {
                // 执行 here 请求
                ofRequestCommand(DemoCmdForSpring.login).execute();
            });
        }
    }

我发现消息发送成功了,但是InternalRegion1 一只监听不到数据,服务端有打印成功:

┏━━━━━ 广播. [(DemoSpringAction.java:80)] ━━━ [cmd:2 - subCmd:1 - cmdMerge:131073]
┣ userId: [1, 1, 1]
┣ 广播数据: DemoUserInfo(phone=链接成功,当前有用户:[1,1,1], password=null)
┣ 广播时间: 2024-05-09 18:06:28.975
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

所以这个广播我有些没有明白耶,麻烦可以解答下吗?

你的代码看上去似乎是没问题的,但在实际中没有尝试过将相同路由分开成两个类来编写的(即 LoginOne、InternalRegion1)。

或许你可以尝试将相同路由的请求与广播监听写在同一个模拟类中,如下

public class DemoRegion extends AbstractInputCommandRegion {
    static final Logger log = LoggerFactory.getLogger(DemoRegion.class);

    @Override
    public void initInputCommand() {
        // 模拟请求的主路由
        inputCommandCreate.cmd = DemoCmd.cmd;

        ofCommand(DemoCmd.login).setTitle("login").setRequestData(() -> {
            return LongValue.of(100);
        });
        
        // ---------------- 广播监听 ----------------
        ofListen(result -> {
            HelloReq value = result.getValue(HelloReq.class);
            log.info("value : {}", value);
        }, DemoCmd.login, "login");

        TaskKit.runOnceSecond(() -> {
            ofRequestCommand(DemoCmd.login).execute();
        });
    }
}
@ActionController(DemoCmd.cmd)
public class DemoAction {

    @ActionMethod(DemoCmd.login)
    public void login(long userId, FlowContext flowContext) {
        UserIdSettingKit.settingUserId(flowContext, userId);

        CmdInfo cmdInfo = CmdInfo.of(DemoCmd.cmd, DemoCmd.login);
        
        HelloReq helloReq = new HelloReq();
        helloReq.name = "aaa : " + userId;

        // 全服广播
        flowContext.broadcast(cmdInfo, helloReq);
    }
}

感谢,整明白了