【问题标题】:Tornado - Send message to client on demandTornado - 按需向客户发送消息
【发布时间】:2015-06-01 01:07:19
【问题描述】:

我正在使用 Tornado 提供一个 html 文件,同时,我希望我的 Python 程序通过 websockets 动态更改同一页面中的值。目的是可以看到值的变化,而不需要在客户端刷新。

在这种情况下,我想发送一条消息,其中的变量每 4 秒从“1234”变为“4321”。 我有一个线程进行值切换,我希望同一个线程将该值发送到 websocket,所以我可以使用客户端的 onmessage 函数通过脚本处理它。

以下代码会给我以下错误:'Application' object has no attribute 'write_message'

import tornado.ioloop
import tornado.web
import tornado.websocket
import threading
import time

flag = True

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("mypage.html")

class wshandler(tornado.websocket.WebSocketHandler):
    def open(self):
        self.write_message('connected')
            print "WebSocket opened"
    def on_message(self, message):
            self.write_message("You have sent: " + message)
    def on_close(self):
            print "WebSocket closed"
    def write_message(self, message):
        print ("writing message", message)
        self.write_message(message)

application = tornado.web.Application(
    handlers=[
        (r"/", MainHandler),
        (r"/ws", wshandler),
        ])

def toggle():
    global flag
    while True:
        if flag==True:
            print 'now on 1234'
            flag = False
            application.write_message('1234')
            time.sleep(4)

        elif flag==False:
            flag = True
            application.write_message('4321')
            print 'Now on 4321'
            time.sleep(4)

def main():
    global response
    valueThread=threading.Thread(target=toggle, name="Toggle Value Thread")
    valueThread.setDaemon(True)
    valueThread.start() 
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()




if __name__ == "__main__":
    main()

我的问题是,我看到的关于 Tornado 的每一个教程/指南都只使用 websocket 类中的 open 和 onmessage 函数中的 write_message 函数。所以我真的不明白为什么这不起作用。

【问题讨论】:

    标签: python tornado


    【解决方案1】:

    您应该只在 websocket 类的 open 和 onmessage 函数中使用 write_message 函数。您正在使用application,即tornado.web.Application。肯定不会有tornado.websocket.WebSocketHandler的方法。他们不是同一个班级。因此出现错误。

    我会这样做:

    class wshandler(tornado.websocket.WebSocketHandler):
    
        def toggle(self):
            flag = True
            while True:
                if flag==True:
                    print 'now on 1234'
                    flag = False
                    self.write_message('1234')
                    time.sleep(4)
    
                elif flag==False:
                    flag = True
                    self.write_message('4321')
                    print 'Now on 4321'
                    time.sleep(4)
    
        def on_message(self, message):
            if message == 'toggle':
                self.toggle()
    

    【讨论】:

    • 谢谢。但是现在我如何在一个线程中使用该函数 wshandler.toggle 来实现一个常量循环?用target=wshandler.toggle创建一个线程会报错。为什么我还需要里面的“onmessage”函数呢?
    • 我只是假设您会在收到诸如“切换”之类的消息时开始切换。这个 wshandler 是只做这一项工作还是什么?
    • Toggle 将作为一个线程启动,并且该线程将在 main 函数中启动。我不想在服务器收到消息后开始切换。我想切换以发送不请自来的消息。它只是服务器发送,而不是等待请求。
    • @DanielPina Websoket 基于 TCP,在传输数据之前需要握手。您需要 UDP 来“发送”数据。
    • @DanielPina 我认为在服务器端切换并不是真正必要的,也不是一个好习惯。这种事情应该在客户端使用Javascript处理。服务器端应该只关注内容生成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-07
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多