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")重载的 open、on_message、on_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());
};
};
});