【问题标题】:How to send a message over websocket at a certain time如何在特定时间通过 websocket 发送消息
【发布时间】:2019-09-17 22:34:25
【问题描述】:

我是 websockets 的新手,刚刚在我的应用程序中获得了一个有效的 websocket 连接。我试图让服务器每分钟在数据库中检查一次以查找即将到来的锦标赛,并且对于连接到从该分钟开始的锦标赛中注册的 websocket 的每个玩家,发送一条消息,表明 ID 为 xxxxx 的锦标赛现在开始。我有以下

比赛/consumers.py:

from channels.generic.websocket import WebsocketConsumer
import json

class TournamentLobbyConsumer(WebsocketConsumer):

    def connect(self):
        self.accept()

    def disconnect(self, close_code):
        pass

    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        print("The websocket received a message: '%s'" % message)

比赛/routing.py:

from django.conf.urls import url

from . import consumers

websocket_urlpatterns = [
    url('ws/tournaments/$', consumers.TournamentLobbyConsumer),
]

比赛/模板/index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Tournament Lobby</title>
</head>

<script>
    var chatSocket = new WebSocket(
        'ws://' + window.location.host +
        '/ws/tournaments/');

    chatSocket.onmessage = function(e) {
        // var data = JSON.parse(e.data);
        // var message = data['message'];
        alert("message received from websocket")
    };

    chatSocket.onclose = function(e) {
        console.error('Chat socket closed unexpectedly');
    };
</script>

{% if tournaments %}

  <ul>
    {% for tournament in tournaments %}
      <li><a href="{% url 'tournament_detail' tournament.id %}"> {{ tournament.name }} {{ tournament.start_time }}</a></li>
    {% endfor %}
  </ul>
{% else %}

  <p>No tournaments are available</p>

{% endif %}



</html>

当我进入这个锦标赛大厅时,我在服务器上收到一条消息,说发生了“websocket 握手”。所以 websocket 连接正在工作。我现在对如何在正在运行的服务器上运行一个循环感到困惑,该循环每分钟检查一次新锦标赛,然后将消息发送到这些连接的客户端。我做的教程只展示了一个服务器响应客户端请求,但是一个 websocket 应该能够在任何一个方向上。

【问题讨论】:

    标签: django websocket django-channels


    【解决方案1】:

    查看apscheduler 以安排您的工作。您的代码如下所示:

    scheduler = BackgroundScheduler()
    scheduler.add_job(check, 'cron', second='*/60')
    scheduler.start()
    
    # Function to run every 60 seconds
    def check():
        pass
    

    【讨论】:

      【解决方案2】:

      您必须首先调用负责发送通知(通道)的消费者方法 https://channels.readthedocs.io/en/latest/topics/channel_layers.html(在消费者之外使用)

      import channels.layers
      from asgiref.sync import async_to_sync
      
      def SimpleShipping(data, **kwargs):
      
        group_name = 'notifications'
        channel_layer = channels.layers.get_channel_layer()
      
        async_to_sync(channel_layer.group_send)(
          group_name,
          {
            'type': 'notify_event',
            'data': data,
            # other: data,
          }
        )
      

      在consumer中声明方法(将consumer添加到通知通道)

      import json
      
      from asgiref.sync import async_to_sync
      from channels.generic.websocket import WebsocketConsumer
      
      class TournamentLobbyConsumer(WebsocketConsumer):
      
        room_group_name = 'notifications'
      
        def connect(self):
          # Join room group
          async_to_sync(self.channel_layer.group_add)(
            self.room_group_name,
            self.channel_name
          )
      
          self.accept()
      
        def disconnect(self, close_code):
          # Leave room group
          async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name,
            self.channel_name
          )
      
        # Receive message from WebSocket
        def receive(self, text_data):
          # ...
          pass
      
        # Receive message from room group (notifications)
        def notify_event(self, event):
          data = event['data']
          # Send message to WebSocket
          self.send(text_data=json.dumps({
            'data': data,
          }))
      
      

      现在你必须选择后台任务的方法(推荐Celery http://docs.celeryproject.org/en/latest/django/first-steps-with-django.html) (看这个问题Django Celery Periodic Task at specific time

      
      from projectname.appname.modulename import SimpleShipping
      
      @shared_task()
      def daily_reports():
        # Run the query in the database.
        # ...
        data = { 'results': 'results' }
        # notify consumers (results)
        SimpleShipping(data)
      
      

      注意:希望对您有所帮助,因为您要实现的任务相当广泛,您不应掉以轻心,尽管此摘要可以让您看到数据的流动

      【讨论】:

        猜你喜欢
        • 2014-07-27
        • 1970-01-01
        • 2018-06-25
        • 1970-01-01
        • 2023-03-15
        • 2023-03-29
        • 2019-05-18
        • 2016-02-16
        • 2021-07-29
        相关资源
        最近更新 更多