HTML5 WebSocket
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
聊天室应用
聊天室要实现的功能:每一个用户登陆/退出,在页面上都要显示该用户登陆/退出;用户发的信息,在每一个用户的页面上都要显示
复制一下以前保存的模板,将项目名改为chatroom
1在templates文件下先写一个登陆页login.html,使用form表单,以post的方式提交登陆数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>登录</h3>
<form action="" method="post">
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
2.在views.py文件下写一个登陆的类视图
这里用户名和密码先写死,后面可加一个注册页,将注册的用户名和密码写入数据库,然后登陆时核对
使用get方法展示页面
# 登录
class LoginHandler(tornado.web.RequestHandler):
def get(self):
self.render('login.html')
3.在urls.py文件下添加一条 LoginHandler的url
url(r'/login/', LoginHandler,name='login'),
查看一下页面是否能展示
4.在views.py文件下增加LoginHandle核对登陆的方法
登陆的信息是以post的方式返回的,写一个方法,如果用户名和密码核对正确的话,设置一个安全的cookie,它会去加密,这是Tornado独有的方式
设置这个cookie加密用的密钥,首先要在__init__ .py文件下的make_app的函数下添加设置,可写在debug的后面
#随机输出一段不重复的24位的十六进制的代码
cookie_secret=os.urandom(24),
如果登陆成功让其进入聊天页面并将当前用户传入聊天页面;如果不成功,就返回一个error显示登陆失败渲染到登录页
def post(self):
username = self.get_body_argument('username')
password = self.get_body_argument('password')
if username in ['xiaoming', 'hh', 'laowang'] and password == '123456':
#设置安全的cookie
self.set_secure_cookie('username', username)
self.render('chat.html', username=username)
else:
error = '用户名或密码错误'
self.render('login.html', error=error)
所以在login.html页面应该有有一个error样式,在form表单前添加一行代码
{% if error %}
<p style="color: red"> {{ error }}</p>
{% end %}
然后LoginHandler这个类函数下的get方法也需要修改一下,先让error为空
def get(self):
error = ''
self.render('login.html', error=error)
如果后面还需要用上首页的话,这里还可以再修改一下首页,添加一个超链接点击跳转到登录页
<a href="{{ reverse_url('login') }}">去登录</a>
5. 写一下聊天页面
chat.html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/css/chat.css">
</head>
<body>
<h3>聊天室</h3>
<p>当前账号:{{ username }}</p>
<div id="chat">
</div>
<input id="content" type="text" >
<input id="send" type="submit" value="发送">
<script src="/static/js/chat.js"></script>
</body>
</html>
css样式,后期可以修改一下,更美观一点
#chat{
width: 500px;
height: 400px;
border: 1px solid black;
}
#content{
width: 400px;
}
6. 定义一个websocket类视图
tornado原生支持websocket这个功能
6.1 导入websocket
import tornado.websocket
6.2 写一下ChatHandler这个类视图
websocket的请求方式不同于get,post,
当一个用户连接到服务器的时候,会自动进入到open函数,当websocket关闭时调用on_close函数
#定义一个websocket类视图
class ChatHandler(tornado.websocket.WebSocketHandler):
#保存用户连接的列表
user_list = []
#当用户连接时调用的函数
def open(self, *args, **kwargs):
#把每个人连接对象加入到列表
self.user_list.append(self)
# 取到进入聊天室人名
username = self.get_secure_cookie('username').decode('utf-8')
#给每个连接的人发送消息
for user in self.user_list:
user.write_message('【%s】 进入了聊天室' % username)
#当websocket关闭时调用的函数
def on_close(self):
#关闭时,把连接删除
self.user_list.remove(self)
# 取到关闭聊天室人名
username = self.get_secure_cookie('username').decode('utf-8')
# 给每个连接的人发送消息
for user in self.user_list:
user.write_message('【%s】 离开了聊天室' % username)
6.3然后去urls.py文件下写一下url路由
url(r'/chat/', ChatHandler,name='chat'),
6.4 聊天的窗口,需要调用jquery建立websocket的连接
去bootstrap网站找到jquery的依赖包,在 起步–>基本模板 依赖包链接
这里直接使用链接导入网上的包,放在网页的head里
<script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
使用js样式,建立建立websocket的连接
//定义一个websocket连接 ws表示协议用的是WebSocket 链接到的url
let websocket = new WebSocket('ws://127.0.0.1:8888/chat/');
//onmessage 当服务器发信息过来的时候会自动调用这个onmessage
//接收服务器消息触发
websocket.onmessage = function (e) {
console.log(e.data);
//取到div里的id
let chat = $('#chat');
chat.append('<br>'); //换行
chat.append(e.data); //加入内容
};
接下来,去浏览器打开三个页面,登陆不同的人
6.5 聊天的内容
写一下js样式
//点击发送聊天内容
$('#send').click(function () {
//取出输入的聊天内容
let content = $('#content').val();
//send给 服务器发送信息
websocket.send(content);
$('#content').val('');
});
写一下类试图函数,让服务器去接收一下这个消息
在views.py文件下的ChatHandler类视图加入一个方法
#接收客户端发送的消息
def on_message(self, message):
print(message)
# 取到发送消息聊天室人名
username = self.get_secure_cookie('username').decode('utf-8')
# 把消息发送给所有人
for user in self.user_list:
user.write_message('[%s]:%s' %(username,message))
去浏览器随便一个用户输入一下发送的消息
聊天室的功能就完成了,可修改增加一些功能
文件链接
链接:https://pan.baidu.com/s/1v2joDd336q-01RJaWU-f4g
提取码:376a