一、基本的文件结构
二、文件内容
1.index.html
该文件为聊天室登录页面,通过在该页面输入的昵称,用以在聊天页面展示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登录首页</title> <link rel="stylesheet" href="/static/libs/bootstrap/bootstrap-3.3.7-dist/css/bootstrap.css"> <script src="/static/libs/jquery/jquery-2.2.4.js"></script> </head> <body> <div class="container"> <div class="panel panel-primary" style="width:60%;"> <div class="panel panel-heading"> 聊天室个人登录 </div> <div class="panel panel-body"> <form class="form-horizontal" method="get" action="/login" style="width:80%"> <div class="form-group"> <label for="nickname" class="col-sm-2 control-label">昵称</label> <div class="col-sm-10"> <input type="text" class="form-control" id="nickname" placeholder="请输入昵称" name="nickname"> </div> </div> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default">登录</button> </div> </form> </div> </div> </div> </body> </html>
页面效果:
2.chat.html
该页面是聊天室页面,重要显示接收数据和发送数据
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>python1709聊天室</title> <link rel="stylesheet" href="/static/libs/bootstrap/bootstrap-3.3.7-dist/css/bootstrap.css"> <link rel="stylesheet" href="/static/app/css/index.css"> <script src="/static/libs/jquery/jquery-2.2.4.js"></script> </head> <body> <div class="container"> <div id="window"> <div class="panel panel-info"> <div class="panel-heading"> 聊天室 </div> <div class="content"> <div class="left"> <div id="personal">个人形象区</div> <img src="/static/app/image/3.jpg" width="300" height="455"> </div> <div class="receive"> </div> <div class="send"> <textarea name="send_content" id="send_content" required> </textarea> <button id="btn" >发送</button> </div> </div> </div> </div> </div> <script> // 创建一个websocket长连接对象 var _websocket= new WebSocket('ws://192.168.11.85:8000/chat') //发送消息 $('#btn').click(function(){ //获取消息内容 $msg=$('#send_content').val(); //发送消息 _websocket.send($msg); $("#msg").val(''); }) //接收消息,当消息更新时自动触发 _websocket.onmessage=function(e){ console.log(e) var $content=e.data; //重构date的Format属性 Date.prototype.Format = function (fmt) { var o = { "M+": this.getMonth() + 1, //月份 "d+": this.getDate(), //日 "H+": this.getHours(), //小时 "m+": this.getMinutes(), //分 "s+": this.getSeconds(), //秒 "q+": Math.floor((this.getMonth() + 3) / 3), //季度 "S": this.getMilliseconds() //毫秒 }; if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); for (var k in o) if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); return fmt; } var date=new Date(); var $time=date.Format("yyyy年MM月dd HH:mm:ss"); var $p1=$('<p>').text($content); var $p2=$('<p>').text($time); $('.receive').append($p2).append($p1) } </script> </body> </html>
页面效果:
3.main.py 文件
''' websocket长连接 聊天室案例 ''' # 引入需要的模块 from tornado.web import RequestHandler, Application,Cookie from tornado.httpserver import HTTPServer from tornado.websocket import WebSocketHandler from tornado.ioloop import IOLoop class BaseHandler(RequestHandler): pass # 定义首页视图处理类,提示用户登录 class IndexHandler(BaseHandler): def get(self): self.render('index.html') # 定义登录视图处理类 class LoginHandler(BaseHandler): def get(self): # 获取用户登录的昵称 nickname=self.get_argument('nickname') # 将用户登录的昵称保存在cookie中,安全cookie self.set_secure_cookie('nickname',nickname,expires_days=None) self.render('chat.html',nickname=nickname) # 定义接收/发送聊天消息的视图处理类,继承自websocket的WebSocketHandler class ChatHandler(WebSocketHandler): # 定义一个集合,用来保存在线的所有用户 online_users = set() # 从客户端获取cookie信息 # 重写open方法,当有新的聊天用户进入的时候自动触发该函数 def open(self): # 当有新的用户上线,将该用户加入集合中 self.online_users.add(self) # 将新用户加入的信息发送给所有的在线用户 for user in self.online_users: user.write_message('【%s】进入了聊天室' % self.request.remote_ip) # 重写on_message方法,当聊天消息有更新时自动触发的函数 def on_message(self, message): # 将在线用户发送的消息通过服务器转发给所有的在线用户 for user in self.online_users: user.write_message('%s:%s' % (self.request.remote_ip, message)) # 重写on_close方法,当有用户离开时自动触发的函数 def on_close(self): # 先将用户从列表中移除 self.online_users.remove(self) # 将该用户离开的消息发送给所有在线的用户 for user in self.online_users: user.write_message('【%s】离开了聊天室~' % self.request.remote_ip) def check_origin(self, origin): return True # 程序运行入口 if __name__=='__main__': import os BASE_DIR=os.path.dirname(__file__) app=Application([ (r'/',IndexHandler), (r'/login',LoginHandler), (r'/chat',ChatHandler), ], template_path=os.path.join(BASE_DIR,'templates'), static_path=os.path.join(BASE_DIR,'static'), debug=True, login_url='/login', cookie_secret='CPFL2FJOTQGzR/8DXZEyfAjxS9hSTk0Bs0f/A12RMnwI8UvYUk5NAbNH/wNdkTJ8') server=HTTPServer(app) server.listen(8000) IOLoop.current().start()