首页 > 解决方案 > django 频道在组用户之间共享实例变量

问题描述

我正在 django 上开发一个在线游戏,我正在使用频道进行实时连接,但不幸的是,对于每个用户,我都有一个单独的游戏实例。

我想要的是,对于第一个用户,我使用对象开始游戏,StartGame并希望对其他用户也使用相同的实例对象,因为我想分享游戏的当前状态。

我怎样才能只与该组的其他成员共享游戏实例?

我的一个想法是将游戏的当前状态保存在一个文件中并将文件的路径保存在数据库中,让另一个用户检索保存的游戏状态并玩他/她的机会并再次保存,但这是一种有效且正确的方法这样做?

网络游戏的实际场景是什么?

更新

我已经实现了,但它是正确的方式还是安全的?

我创建了一个全局变量GAME_POOL = {},并为第一个用户存储了带有键的 Game 实例,channel_group_name然后为其他用户检查是否GAME_POOL有现有值,channel_group_name然后设置self.game = GAME_POOL['channel_group_name']及其工作。

但同样,这是实现这一目标的安全和好方法吗?

我在游戏结束后删除这个。

标签: djangopython-3.xwebsocketdjango-channels

解决方案


如果您真的想将游戏状态存储在 RAM 中(尽管 Ken4scholars 在评论中提到了限制),您还可以将共享变量移动到中间件中,如下所示:

from channels.middleware import BaseMiddleware


class GameStateMiddleware(BaseMiddleware):
    def __init__(self, inner):
        self.inner = inner
        self.game_states = {}

    async def __call__(self, scope, receive, send):
        query = dict((qp.split('=') for qp in scope['query_string'].decode().split("&")))
        game_id = query.get('game_id')

        if game_id not in self.game_states:
            game_states[game_id] = {}

        scope['game_state'] = self.game_states[game_id]
        return await super().__call__(scope, receive, send)

在消费者内部,共享变量将在self.scope['game_state']. 由于它是通过引用传递的,因此您也可以对其进行写入,但是,您需要注意同步(例如,还将锁注入范围)。


推荐阅读