长轮询:客服端不停的给服务端发起请求(一直请求浪费流量)
websocket:是服务器和客服端一直连接起来
websocket协议是基于TCP的HTML5协议
1.首先导入 import tornado.websocket
2.写一个Base类,继承 tornado.websocket.WebSocketHandler
class BaseWebSoketHandler(tornado.websocket.WebSocketHandler, SessionMixin): # Session为redis加密cookie需要继承类 def get_current_user(self): # 重写 current_user = self.session.get('ID') # 通过redi加密时登陆时发送的cookie,现在在这儿获取cookie信息 if current_user: return current_user return None
# redis 加密需要的Base类
class BaseHandler(tornado.web.RequestHandler, SessionMixin): def get_current_user(self): current_user = self.session.get('ID') if current_user: return current_user return None
# 登陆界面
class LoginHandler(BaseHandler): def get(self): nextname = self.get_argument('next','') self.render('login_1.html', # form表单 nextname=nextname, error='' ) def post(self, *args, **kwargs): name = self.get_argument('name','') password = self.get_argument('password','') username = User.by_name(name) nextname = self.get_argument('next','') print(name, password, nextname) if username and username.password==password: # self.set_secure_cookie('ID', name, httponly=True) self.session.set('ID',name) # if nextname: self.redirect(nextname) else: self.redirect('/') else: self.render('login_1.html', nextname=nextname, error='用户名或密码错误' )
# 登陆后返回 聊天交互界面
class IndexHandler(BaseHandler): @authenticated def get(self): self.render('08websocket.html')
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
08websocket.html
<body> <div class="box"> <div> <textarea id="text" placeholder="请输入您的内容"></textarea> <a href="javascript:WebSocketSend();" class="btn btn-primary">发送</a> </div> <ul id="messages"> </ul> </div> <script src="{{ static_url('js/jquery-2.2.0.min.js') }}"></script> <script type="text/javascript"> var mes = document.getElementById('messages'); if("WebSocket" in window){ mes.innerHTML = "发送WebSocket请求成功!"; var ws = new WebSocket("ws://127.0.0.1:8000/websocket"); ws.onopen = function () { alert('连接已打开请聊天') }; ws.onmessage = function (goudan) { var received_msg = goudan.data; var aLi = $("<li>"+received_msg+"</li>"); $(mes).append($(aLi)) // 方法一 // $(aLi).appendTo(mes); // 方法二 }; ws.onclose = function () { mes.innerHTML = mes.innerHTML + "<br>连接已经关闭..."; }; } else { mes.innerHTML = "发送WebSocket请求失败!" } function WebSocketSend() { ws.send($("#text").val()); } </script> </body>
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3.发送massage到浏览器
class MassageHandler(BaseWebSoketHandler):
user = set()
# 写入这三个方法
# 登陆时
def open(self, *args, **kwargs):
MassageHandler.user.add(self)
print(self)
for i in self.user:
i.write_message(' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
i.write_message('欢迎%s进入聊天室... %s先生是尊贵的VIP1000 ❀'%(self.current_user,self.current_user))
i.write_message( '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
print('-----websocket open------')
# 聊天发送消息
def on_message(self, message):
for i in self.user:
i.write_message('%s-%s-说: %s' %(
self.current_user,
datetime.now().strftime('%Y-%m-%d %H-%M-%S'),
message
))
# 退出登录
def on_close(self):
if self in MassageHandler.user:
MassageHandler.user.remove(self)
//
application = tornado.web.Application( handlers=[ (r"/login", LoginHandler), (r"/", IndexHandler), (r"/websocket", MassageHandler), ], template_path='templates', static_path='static', login_url='/login', cookie_secret='haha', pycket={ 'engine': 'redis', # 连接redis 'storage': { 'host': 'localhost', # 本机 'port': 6379, # redis端口 'db_sessions': 5, # redis的数据库(0-15个) 'db_notifications': 11, 'max_connections': 2 ** 31, }, 'cookies': { # cookie 过期时间 'expires_days': 30, 'max_age': 100 }, }, debug=True )
if __name__ == '__main__': tornado.options.parse_command_line() # 获取命令行的参数 --port=1040 就能使用这个参数 print(options.port) print(options.version) http_server = tornado.httpserver.HTTPServer(application) application.listen(options.port) tornado.ioloop.IOLoop.instance().start()