使用Tornado向客户端发送间歇性更新

0 投票
1 回答
791 浏览
提问于 2025-04-18 10:08

我写了一个简单的 Tornado 应用,使用 WebSocket 来管理后台进程(就像 Transmission 的网页界面一样)。有一件事让我困扰,就是状态更新的实现。

我的 WebSocketHandler 只接收来自客户端的消息,执行必要的操作,检查状态,然后把状态发送回客户端。它不会在没有请求的情况下主动发送状态给客户端。

class WebSocketHandler(tornado.websocket.WebSocketHandler):

    def open(self):
        print('connected')
        self.daemon = Daemon()
        self.write_message(self.daemon.get_status())

    def on_message(self, message):
        if message == 'start':
            self.daemon.start()
        elif message == 'stop':
            self.daemon.stop()
        self.write_message(self.daemon.get_status())

    def on_close(self):
        print('disconnected')

我在客户端使用了 JavaScript 的 setInterval 函数来定期请求状态更新,像这样:

        ws = new WebSocket("ws://localhost:8080/websocket");

        ws.onopen = function () {
          setInterval(function() {
            if (ws.bufferedAmount == 0)
              ws.send('status');
          }, 1000);
        };
    }

那么,如何在服务器端实现相同的效果,让 Tornado 能够主动发送当前状态给客户端,而不阻塞 on_message 方法呢?

1 个回答

7

你可以使用 tornado.ioloop.IOLoop.add_timeout 这个方法,每隔X秒调用一次某个方法来更新客户端的信息:

from tornado.ioloop import IOLoop
from datetime import timedelta

class WebSocketHandler(tornado.websocket.WebSocketHandler):

    def open(self):
        print('connected')
        self.daemon = Daemon()
        self.write_message(self.daemon.get_status())
        self.schedule_update()

    def schedule_update(self):
        self.timeout = IOLoop.instance().add_timeout(timedelta(seconds=5),
                                                     self.update_client)
    def update_client(self):
        try:
            self.write_message(self.daemon.get_status())
        finally:
            self.schedule_update()

    def on_close(self):
        IOLoop.instance().remove_timeout(self.timeout)
        print('disconnected')

撰写回答