Tornado对异步的支持比较好,与websocket 搭配实现监控类的应用更为简便些。 在tornado的github 上有关于websocket的一个聊天室应用示例。
实际代码部分如下:
class ChatSocketHandler(tornado.websocket.WebSocketHandler):
waiters = set()
cache = []
cache_size = 200
def open(self):
ChatSocketHandler.waiters.add(self)
def on_close(self):
ChatSocketHandler.waiters.remove(self)
@classmethod
def update_cache(cls, chat):
cls.cache.append(chat)
if len(cls.cache) > cls.cache_size:
cls.cache = cls.cache[-cls.cache_size :]
@classmethod
def send_updates(cls, chat):
logging.info("sending message to %d waiters", len(cls.waiters))
for waiter in cls.waiters:
try:
waiter.write_message(chat)
except:
logging.error("Error sending message", exc_info=True)
def on_message(self, message):
logging.info("got message %r", message)
parsed = tornado.escape.json_decode(message)
chat = {"id": str(uuid.uuid4()), "body": parsed["body"]}
chat["html"] = tornado.escape.to_basestring(
self.render_string("message.html", message=chat)
)
ChatSocketHandler.update_cache(chat)
ChatSocketHandler.send_updates(chat)
首先定义一个WebSocketHandler类,然后定义全局的waiters (所有参与聊天的用户)和 cache(聊天内容)。waiters中实际存储的是WebSocketHandler类的实例入口,通过这个waiters可以访问到实例,然后通过websocket 与客户端通信。
waiters 是一个集合,在open和close 阶段,仅仅将实例入口加入集合或从集合中删除。
update 和 send_update部分忽略,直接来看on_message 部分,这个部分是当有新消息时服务器端的处理,这里时通过render_string 方法生成关于消息的部分页面文件。
render_string与render有什么区别?render_string方法是根据一个模板的名字和字典参数,对模板进行渲染,返回的是一个内容页面字符串。而render方法会将渲染的结果,发送到客户端。参考 https://blog.csdn.net/wyx819/article/details/45652713
然后通过update_cache 更新聊天内容的cache,通过send_updates 将聊天内容发送给所有客户端。在 send_updates方法中,通过遍历waiters 列表,将聊天内容逐个发送给所有参与聊天的客户端。
在js 部分,通过 $document.ready()方法在页面加载完毕后执行js代码,与服务器建立websocket链接,并通过onmessage 接收和处理服务器发送来的数据。
$(document).ready(function() {
if (!window.console) window.console = {};
if (!window.console.log) window.console.log = function() {};
$("#messageform").on("submit", function() {
newMessage($(this));
return false;
});
$("#messageform").on("keypress", function(e) {
if (e.keyCode == 13) {
newMessage($(this));
return false;
}
});
$("#message").select();
updater.start();
});
start: function() {
var url = "ws://" + location.host + "/chatsocket";
updater.socket = new WebSocket(url);
updater.socket.onmessage = function(event) {
updater.showMessage(JSON.parse(event.data));
}
},
聊天室需要处理页面发送消息和接收消息两个方向,要复杂些。下节将监控的思路整理下。