Python中WebSocket服务器定期发送消息

3

我有一个用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
嗨,Thijs van Dien, 感谢您,但是如何删除回调? - Snigdha
我尝试了这个: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()但是出现了错误:Traceback (most recent call last): File "/Library/Python/2.7/site-packages/tornado/ioloop.py", line 814, in _run self.callback() TypeError: 'NoneType' object is not callable ERROR:tornado.application:Error in periodic callback - Snigdha
你不能向回调方法提供参数;你需要传递它,而不是调用它 - 请参见下面的示例。 - Thijs van Dien
3个回答

5
这是一个使用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 我强烈建议你阅读《Introduction to Tornado》中关于异步Web编程的章节:http://www.amazon.com/Introduction-Tornado-Michael-Dory/dp/1449309070 - Thijs van Dien
如何在Python中编写我们自己的RestAPI? - Snigdha
1
@Snigdha,你偏离了主题。REST API通常作为常规HTTP实现,而不是Websockets。无论如何,每个问题(主题)一个问题。 - Thijs van Dien
列表可以传递给self.write吗?我的意思是self.write(samplelist)。这可能吗?我尝试了这个,但是出现了断言错误。请帮帮我。 - Snigdha

0
你正在调用函数而不是启动计时器。请按照以下步骤操作:
threading.Timer(10, self.msg, args =('in timer',)).start()

我认为使用 threading 是不合适的。Tornado是异步的,并且具有自己的执行计划命令的工具。 - Thijs van Dien
嗨,谢谢。我尝试了这个,但是当我从客户端关闭连接时,我会收到错误。 - Snigdha

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接