如何在特定时间通过websocket发送消息

时间:2019-09-17 22:34:25

标签: django websocket django-channels

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

tournaments / consumers.py:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset=utf-8">
    <title>Mocha Tests</title>

    <link href="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.css" rel="stylesheet" />   

  </head>
  <body>
    <div id="mocha"></id>
    <div id="messages"></div>

<script src="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/4.2.0/chai.js"></script>   
    <script type="module" class="mocha-init">
        mocha.setup('bdd');
    </script>

    <script src="test.js"></script>
    <script type="module"> 
        mocha.run();
    </script>

  </body>
</html>

tournaments / routing.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)

tournaments / templates / index.html:

from django.conf.urls import url

from . import consumers

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

当我去这个锦标赛大厅时,我在服务器上收到一条消息,表明“网络套接字握手”已经发生。因此,websocket连接正在工作。我现在对如何在正在运行的服务器上运行循环感到困惑,该服务器每分钟检查一次新的锦标赛,然后将消息发送到这些连接的客户端。我完成的教程仅显示了服务器对客户端请求的响应,但是websocket应该能够朝任一方向运行。

2 个答案:

答案 0 :(得分:1)

签出apscheduler来安排您的工作。您的代码如下所示:

scheduler = BackgroundScheduler()
scheduler.add_job(check, 'cron', second='*/60')
scheduler.start()

# Function to run every 60 seconds
def check():
    pass

答案 1 :(得分:1)

您必须首先调用负责发送通知的消费者方法(渠道) 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,
    }
  )

在使用者中声明方法(将使用者添加到通知通道)

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)

注意:我希望它会有所帮助,因为您要执行的任务相当广泛,因此您不应掉以轻心,尽管此摘要将使您看到数据流