Python Tornado之WebSocket聊天室
项目背景
最近有个血压项目,需要用到python tornado+websocket+com通讯,所以会逐渐写出来。
之前弄的是Springboot2的ws,SpringBoot2.0集成WebSocket,实现后台向前端推送信息,现在由于java com口通讯没有python好用,所以改用Python这套。
WebSocket连接
WebSocket和Http轮询的都是客户端和服务器之间是持久通信的方式,使用情况可根据场景进行优化选择,Http轮询一般可以跟缓存很好结合,Ws连接一般可以更快相应并从后端往前端推送。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
TornadoWebSocket模块
Tornado在websocket模块中提供了一个WebSocketHandler类,这个类提供了和已连接的客户端通信的WebSocket事件和方法的Handler。
- open方法,新的WebSocket连接打开时被调用。
- on_message方法:连接收到新消息时被调用。
- on_close方法:客户端关闭时被调用。
- write_message方法:向客户端发送消息时被调用。
- close方法:关闭连接时调用。
chat-server.py(服务端代码)
# coding:utf-8
import tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
import os
import datetime
from tornado.web import RequestHandler
from tornado.options import define, options
from tornado.websocket import WebSocketHandler
define("port", default=2222, type=int)
class IndexHandler(RequestHandler):
def get(self):
self.render("chat-client.html")
class ChatHandler(WebSocketHandler):
users = set() # 用来存放在线用户的容器
def open(self):
self.users.add(self) # 建立连接后添加用户到容器中
for u in self.users: # 向已在线用户发送消息
u.write_message(u"[%s]-[%s]-进入聊天室" % (self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
def on_message(self, message):
for u in self.users: # 向在线用户广播消息
u.write_message(u"[%s]-[%s]-说:%s" % (self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), message))
def on_close(self):
self.users.remove(self) # 用户关闭连接后从容器中移除用户
for u in self.users:
u.write_message(u"[%s]-[%s]-离开聊天室" % (self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
def check_origin(self, origin):
return True # 允许WebSocket的跨域请求
if __name__ == '__main__':
tornado.options.parse_command_line()
app = tornado.web.Application([
(r"/", IndexHandler),
(r"/chat", ChatHandler),
],
static_path = os.path.join(os.path.dirname(__file__), "static"),
template_path = os.path.join(os.path.dirname(__file__), "template"),
debug = True
)
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.current().start()
template\chat-client.html(客户端代码)
如果是通过http web访问,请放在chat-server.py
目录下的template\chat-client.html
,如果是文件直接访问,就直接拖到浏览器访问即可。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>聊天室</title>
</head>
<body>
<div id="contents" style="height:500px;overflow:auto;"></div>
<div>
<textarea id="msg"></textarea>
<a href="javascript:;" onclick="sendMsg()">发送</a>
</div>
<!-- jQuery -->
<script src="https://cdn.staticfile.org/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
var ws = new WebSocket("ws://127.0.0.1:2222/chat");
ws.onmessage = function(e) {
$("#contents").append("<p>" + e.data + "</p>");
}
function sendMsg() {
var msg = $("#msg").val();
ws.send(msg);
$("#msg").val("");
}
</script>
</body>
</html>