oldbee0925 2023-03-24 10:57 采纳率: 91.4%
浏览 63
已结题

请教一个django channel websocket同步与异步、group分组与向特定用户发信息的问题。

我用django、websocket开发一个在线扑克游戏,遇到问题请教。
我的意图,也是扑克游戏的普通规则:
1、利用django自带的auth模块,建立有不同的3个用户;
2、3个用户不会同时进入牌室,等到最后(第3个用户登录并send准备好的指令)进入,后端发不同的牌给3个用户;
3、出牌时,所有用户都能看到。
这里涉及到几个概念:
1、关于群发与私发。对于发牌,是一对一向指定用户私发;对于出牌,则是群发。怎样实现群发与私发?
2、等待用户到齐,这个需要用异步模式吗?还是不一定?或者这个阶段用ajax请求?
脑袋一团雾水,请教各位的指点,最好有代码及注释说明(channel模块)!谢谢!

  • 写回答

3条回答 默认 最新

  • $encoding 2023-03-24 15:38
    关注

    好的,我来回答您的问题,同时提供代码及注释说明。

    1. 群发与私发

    对于私发,我们可以使用Django Channels库中提供的一些工具来实现。如下所示:

    from channels.layers import get_channel_layer
    from asgiref.sync import async_to_sync
    
    channel_layer = get_channel_layer()
    
    # 向指定用户发送消息
    async def send_card(user_id, message):
        # 获取接收消息的通道名,这里我假设通道名为"game_channel"
        channel_name = f"game_channel_{user_id}"
        # 同步发送消息到指定通道
        await async_to_sync(channel_layer.send)(channel_name, {"type": "send_card", "message": message})
    

    对于群发,我们可以使用WebSocket来实现。如下所示:

    # 在 consumers.py 中定义 WebSocket 处理函数
    async def receive_card(self, event):
        # 从事件中获取需要发送的消息
        message = event["message"]
        # 向 WebSocket 发送群发消息
        await self.send(text_data=json.dumps({
            "event": "receive_card",
            "message": message
        }))
    
    1. 等待用户到齐

    对于等待用户到齐,可以使用异步模式。如下所示:

    from channels.layers import get_channel_layer
    from asgiref.sync import async_to_sync
    
    channel_layer = get_channel_layer()
    
    # 定义一个触发器,判断是否所有用户都已经准备好了
    async def trigger_ready(user_id):
        # 查询所有用户是否都已经准备好了,这里可以用一个 signal 记录用户的状态
        all_ready = all([user1_ready, user2_ready, user3_ready])
        if all_ready:
            # 执行到这里,说明所有玩家已经准备好了,我们就可以开始发牌了。
            # 随机生成牌堆,并且给每个玩家发牌
            # 然后群发一条消息,告诉所有玩家,现在可以开始操作了
            await channel_layer.group_send("game_group", {
                "type": "start_game",
                "message": "游戏开始了,请开始操作。"
            })
        else:
            # 如果还没有到齐,就延迟一秒继续触发
            await asyncio.sleep(1)
            await trigger_ready(user_id)
    
    # 在 consumers.py 中定义 WebSocket 处理函数
    async def connect(self):
        # 获取当前 WebSocket 的 user_id
        user_id = self.scope["user"].id
        # 将该 WebSocket 加入 game_group 通道组,以便后续群发消息
        await self.channel_layer.group_add("game_group", self.channel_name)
        # 将该 WebSocket 加入到自己的通道,后续用于私发消息
        await self.channel_layer.group_add(f"game_channel_{user_id}", self.channel_name)
        # 发送准备状态到后端,这里可以用一个 signal 记录用户的状态
        ready_signal.send(sender=user_id)
        # 触发等待用户到齐的逻辑
        await trigger_ready(user_id)
        
    async def disconnect(self, close_code):
        # 获取当前 WebSocket 的 user_id
        user_id = self.scope["user"].id
        # 将该 WebSocket 移除 game_group 通道组
        await self.channel_layer.group_discard("game_group", self.channel_name)
        # 将该 WebSocket 移除自己的通道
        await self.channel_layer.group_discard(f"game_channel_{user_id}", self.channel_name)
    

    以上代码仅作为参考,不保证完全准确。需要根据实际项目需求进行修改。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 3月30日
  • 已采纳回答 3月30日
  • 创建了问题 3月24日

悬赏问题

  • ¥15 (标签-UDP|关键词-client)
  • ¥15 关于库卡officelite无法与虚拟机通讯的问题
  • ¥15 qgcomp混合物线性模型分析的代码出现错误:Model aliasing occurred
  • ¥100 已有python代码,要求做成可执行程序,程序设计内容不多
  • ¥15 目标检测项目无法读取视频
  • ¥15 GEO datasets中基因芯片数据仅仅提供了normalized signal如何进行差异分析
  • ¥100 求采集电商背景音乐的方法
  • ¥15 数学建模竞赛求指导帮助
  • ¥15 STM32控制MAX7219问题求解答
  • ¥20 在本地部署CHATRWKV时遇到了AttributeError: 'str' object has no attribute 'requires_grad'