4

我已经使用 erlang 的消息传递构造构建了一个多人游戏(准确地说是 4 个玩家)。我以以下链接上的 tictactoe 游戏为例,但真正相似的是游戏中显示的消息传递构造:link

然后我选择在 ejabberd Multi user Chatroom 上运行这个游戏,我确实为此编写了一个 ejabberd 钩子。但是,如果您查看上述链接中文件 tictactoe.erl 中的 NewGameState,您会发现无法在变量中检索它。

所以我使用了 mnesia 并将每个生成的新游戏状态写入这个 mnesia 表。现在在我的 ejabberd 钩子中,我调用我的游戏函数(即在每次调用时执行一系列模块->“gen_server,game_modules,mnesia_modules”)并在游戏函数调用下方的钩子中,我正在从 mnesia 表中读取游戏状态如下(这里的函数myMessage是ejabberd钩子里面的函数):

myMessage({#message = Msg, C2SState})->
    some_other_module:game_func(Args),
    State=mnesia_module:read(key),

    {Msg, C2SState};
myMessage(Acc) ->
    Acc.

现在我的问题是,当执行顺序为时,读取操作给了我一个空表

some_other_module:game_func(Args),
 GameState=mnesia_module:read(key),

当我在这两行之间插入延迟时,timer:sleep/1如下所示(经过一些不同值的试验后随机选择值 200):

some_other_module:game_func(Args),
timer:sleep(200)
 GameState=mnesia_module:read(key),

我得到了正确的 GameState 值,因此建议我进行读取操作

GameState=mnesia_module:read(key),

在行some_other_module:game_func(Args)(这是一系列模块->“gen_server,game_modules,mnesia_modules”)能够执行 mnesia 模块并将 GameState 写入 mnesia 表之前执行/执行。

如何解决此问题,因为我不想使用timer:sleep/1它,因为它不是可靠的解决方案。

谁能建议我在这里解决一下。我的意思是,任何人都可以建议我一种方法来通过除 mnesia 以外的任何其他方式来检索钩子内的 GameState,所以我根本没有竞争条件。

或者,ejabberd 是否以某种方式提供了一些我可以在这里使用的功能?

提前致谢。

4

2 回答 2

5

分布式节点之间数据的实时一致性是一个难题,您需要根据自己的需要定制解决方案。你没有说你正在使用什么样的交易与 mnesia,所以也许这会解决你的问题。

但是,这里有一个简单的解决方案可以帮助您思考问题:

首先,让我们调用您的一个节点master。在主节点上,启动一个处理游戏状态的 gen_server。现在,任何想要读取或写入游戏状态的人都需要rpc:call/4将主节点(除非他们已经在那里)制作成gen_server:call/2. 现在所有与游戏状态的交互都是同步的。

如果您每秒更新游戏状态不超过几次,则此解决方案应该非常适合您。如果游戏是独立的,那么每个游戏都是不同的 gen_server。

于 2017-08-12T04:50:09.790 回答
1

我正在尝试提供对我有用的解决方案。希望它可以帮助某人。

这是我所做的:

首先,我从图片中删除了失忆症。

我首先在函数内部创建基本模块的 Pid 后立即注册它start/2(您可以想到问题中提供的链接上存在的 tictactoe.erl),然后我get_gs/0在该模块中创建了一个函数,仅将 GameState 检索为如下(server是我用来注册 Pid 的别名):

get_gs()->
    server ! {get_gs, self()},
     receive
        GameState ->
            GameState
    end.

然后在loop()我拥有的功能内部:

{ get_gs, From } ->
           From ! GameState,

           loop(FirstPlayer, SecondPlayer, CurrentPlayer, GameState)

然后创建一个实现 gen_server 架构的模块并按以下顺序调用一个函数(其中->表示函数调用,如 A->B 表示从 A 我调用 B):

My custom hook on ejabberd->gen_server based module->gameclient:get_gs/0->gameserver:get_gs/0->tictactoe:get_gs/0

我得到了当前的 GameState。

谢谢@Nathaniel Waisbrot 的宝贵建议。

于 2017-08-12T13:53:32.653 回答