听同事说了用websocket可以实现实时,工作之余研究下
1.百度了下,websocket支持双向实时通信,知乎上说的更具体些,一开始使用http握个手,然后开始数据传送
2.看了下tornado websocket源码、注释(google翻译),好痛苦
3.网上找了个例子,但是用不了,自己改了些东西,简单实现从web端发一个string,经过server,再回到web端显示出来
开了服务器,web端报403,覆盖check_origin,返回true解决。
def check_origin(self, origin):
return True
4,上一个实现的是在server接收到消息后直接执行发送消息,但是要实现服务器主动发消息,没找到资料(百度的。。没翻墙),问大神用TCPServer 往stream里写,折腾半天未果(百度的。。)
5,使用类方法@classmethod,每创建一个连接,就把该websocket实例传给类变量(list),断开连接移除该实例。接收到消息后遍历list,用它发送消息,实现了聊天。
服务器代码:
class ChatSocketHandler(tornado.websocket.WebSocketHandler):
examples = []
@classmethod
def addClass(cls, example):
cls.examples.append(example)
@classmethod
def removeClass(cls, example):
cls.examples.remove(example)
#建立连接时调用,建立连接后将该websocket实例存入ChatSocketHandler.examples
def open(self):
self.addClass(self)
print("WebSocket opened")
#收到web端消息时调用,接收到消息,使用实例发送消息
def on_message(self, message):
print("WebSocket on_message ")
for ex in ChatSocketHandler.examples:
ex.write_message(u"You said: " + message)
#断开连接时调用,断开连接后删除ChatSocketHandler.examples中的该实例
def on_close(self):
self.removeClass(self)
print("WebSocket on_closed")
#403就加这个
def check_origin(self, origin):
print("check_origin")
return True
#用于发送消息到web端
def write_message(self, message, binary=False):
print("write_message" + message)
if self.ws_connection is None:
raise WebSocketClosedError()
if isinstance(message, dict):
message = tornado.escape.json_encode(message)
self.ws_connection.write_message(message, binary=binary)
#主动关闭连接
def close(self, code=None, reason=None):
print("close ")
if self.ws_connection:
self.ws_connection.close(code, reason)
self.ws_connection = None
js代码
socket = new WebSocket("ws://localhost:8080/...");
//连接建立成功后调用,在这里是建立成功后给服务去发了一个‘start’
socket.onopen = function() {
//web端发送消息方法
socket.send("start");
};
//web端收到消息时调用
socket.onmessage = function (evt) {
$("#cl").append('<p>'+evt.data+'<p>')
};
终于,实时、主动发消息还是粗糙的实现了(使用ChatSocketHandler.examples),后续研究用TCPServer实现server主动发消息,然后该翻墙google了。。。