Tornado 与 WebSocket 实现实时聊天室

阅读 1722
收藏 43
2016-06-01
原文链接:mp.weixin.qq.com

WebSocket 是用于浏览器与服务器之间进行双相连接的协议,可以用于创建基于浏览器的实时聊天工具。Tornado 自身支持 WebSocket 协议,也可以用来接收网站管理员的编辑指令。

根据官方文档,可以通过继承 tornado.websocket.WebSocketHandler 处理来自 WebSocket 协议的请求:

class EchoWebSocket(tornado.websocket.WebSocketHandler):
  def open(self):
    print("WebSocket opened")
 def on_message(self, message):    self.write_message(u"You said: " + message)
 def on_close(self):    print("WebSocket closed")

重载的 openon_messageon_close 方法分别用于处理连接创建时、接收信息时和连接关闭时的相关操作。对应的浏览器端操作为:

var ws = new WebSocket("ws://"+window.location.host+"/websocket");
ws.onopen = function() {
  ws.send("Hello, world");
};
ws.onmessage = function (evt) {   
 console.log(evt.data); };

首先需要创建聊天页面:

class ChatWebHandler(BaseController):
  def get(self):
    self.render("chat/index.html")
 def post(self):        uid = self.get_body_argument("uid")    self.set_secure_cookie("uid", uid)    self.redirect("/chat") router = [  (r'/chat', ChatWebHandler), ]

如果是多人聊天,需要保存所有的请求对象,并在有消息进入时更新所有连接:

from datetime import datetime
class EchoWebSocket(tornado.websocket.WebSocketHandler):  pool = set()
 def open(self):    EchoWebSocket.pool.add(self)  
 def on_close(self):    EchoWebSocket.pool.remove(self)
 def on_message(self, message):    uid = self.get_secure_cookie("uid")    uid = uid.decode() if uid is not None else "匿名"    EchoWebSocket.update(dict(      uid = uid,      msg = message,      t   = datetime.now().strftime("%m-%d %H:%M:%S")    ))
 @classmethod  def update(cls, msg):    for chat in cls.pool:      chat.write_message(msg) router = [  (r'/ws', WebSocketHandler),  (r'/chat', ChatWebHandler)  ]

浏览器客户端接收和发送消息:

$(document).ready(function(){
 var input = $('#msgInput');  
 var frame = $('#msgFrame');
 var wraper= $('#msgWraper');  
 var ws = new WebSocket("ws://" + window.location.host + "/ws");
   $('#msgForm').on('submit', function (e) {
   var msg = input.val();    input.val('');    ws.send(msg);
   return false;  });  
   ws.onmessage = function (evt) {
   var data = JSON.parse(evt.data);    
       frame.append($('
  • '
  • + data.uid+': '+ data.message + '' + data.t +''));
       if (frame.height() >= wraper.height()) {      wraper.scrollTop(frame.height());    };  }; });


    评论