【问题标题】:WebSocket Server sending messages periodically in pythonWebSocket Server在python中定期发送消息
【发布时间】:2013-10-23 12:56:49
【问题描述】:

我在 python 中有一个 Tornado Web 服务器:

import tornado.httpserver
import tornado.websocket
import tornado.ioloop
from tornado.ioloop import IOLoop
import tornado.web
import time
import   threading
import sys
from datetime import datetime
from datetime import timedelta

def sample():
    print 'hiiiii'
    threading.Timer(10, sample).start()

class WSHandler(tornado.websocket.WebSocketHandler):

    def open(self):
        print 'new connection'

    def on_message(self, message):
        self.write_message(message)  
        self.msg('hellooooooo')
        print message

    def msg(self,message):
        self.write_message(message)
        threading.Timer(10, self.msg('in timer')).start()
        print 'in msg'+message
    def on_close(self):
        print 'connection closed'

application = tornado.web.Application([
    (r'/', WSHandler),
])

if __name__ == "__main__":
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(8888)
    interval_ms=120
    main_loop=tornado.ioloop.IOLoop.instance()
main_loop.start()

而客户是

<html>
<head>
<script> 

function fun(){

    alert("in fun()");

    var val=document.getElementById("txt");
    var ws = new WebSocket("ws://localhost:8888");

    ws.onopen = function(evt) { alert("Connection open ...");
    ws.send(val.value); };
    ws.onmessage = function(evt) {
         alert("from server: "+evt.data);
    }

    ws.onclose = function(evt) { 
        alert("Connection closed.");
    }
}

</script>

</head>
<body bgcolor="#FFFFFF">
    <input type="text" id="txt" />
    <button onClick="fun()">click</button>
</body>
</html>

我想定期将消息发送给客户端。但是当我尝试这个时,我得到了这个错误:RunTimeError :Maximum Recursion Depth Exceeded. 请帮我解决这个问题。另外,我们如何知道连接到服务器的客户端是什么?

【问题讨论】:

  • 不要使用threading。看看IOLoop.add_timeout,尤其是tornado.ioloop.PeriodicCallback。关闭连接时不要忘记删除回调。
  • 您好 Thijs van Dien,谢谢,但是如何删除回调?
  • 我试过这个 def open(self): print 'new connection' main_loop=tornado.ioloop.IOLoop.instance() scheduler=tornado.ioloop.PeriodicCallback(self.msg('testing'), interval_ms,io_loop=main_loop) scheduler.start() main_loop.start() 但出现错误:回溯(最近一次调用最后一次):文件“/Library/Python/2.7/site-packages/tornado/ioloop.py”,行814,在 _run self.callback() TypeError: 'NoneType' object is not callable ERROR:tornado.application:Error in period callback
  • 你不能为回调方法提供参数;您需要传递它,而不是调用它 - 请参阅下面的示例。

标签: python websocket tornado periodic-task


【解决方案1】:

这是一个使用 PeriodicCallback 的最小示例。

import tornado.httpserver
import tornado.websocket
import tornado.ioloop
from tornado.ioloop import PeriodicCallback
import tornado.web

class WSHandler(tornado.websocket.WebSocketHandler):
    def open(self):
        self.callback = PeriodicCallback(self.send_hello, 120)
        self.callback.start()

    def send_hello(self):
        self.write_message('hello')

    def on_message(self, message):
        pass

    def on_close(self):
        self.callback.stop()

application = tornado.web.Application([
    (r'/', WSHandler),
])

if __name__ == "__main__":
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

【讨论】:

  • @user2911377 我强烈建议您阅读 Tornado 简介中关于异步 Web 编程的章节:amazon.com/Introduction-Tornado-Michael-Dory/dp/1449309070
  • 如何用Python编写我们自己的RestAPI?
  • @Snigdha 你跑题了。 REST API 通常实现为常规 HTTP,而不是 websocket。不管怎样,每个问题一个问题(主题)。
  • 可以将列表传递给 self.write 吗?我的意思是 self.write(samplelist)。这可能吗?我试过这个得到断言错误。请帮助我
【解决方案2】:

您正在调用函数而不是启动计时器。这样做:

threading.Timer(10, self.msg, args =('in timer',)).start()

【讨论】:

  • 我认为使用threading 是不合适的。 Tornado 是异步的,并且有自己的工具来按计划执行命令。
  • 嗨谢谢我试过这个但是当我关闭来自客户端的连接时出现错误
【解决方案3】:

这些例子对你有帮助吗

Tornado example

这也是Documentation tornado WS

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-30
    • 2021-12-26
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 2018-04-20
    • 1970-01-01
    相关资源
    最近更新 更多