tornado 10 长轮询和 websocket
一、长轮询
#在网页,我们经常扫码登录,那么问题来了,前端是如何知道用户在手机上扫码登录的呢
这里就需要用到长轮询
#长轮询 #客户端能够不断地向服务器发送请求 #缺点:1、开销大 2、浪费资源 3、消耗流量
二、websocket
#由于长轮询消耗太多资源,主要原因是客户端和服务器并没有连接在一起,那么怎样能够让客户端和服务器一直保持连接? #这就需要用到WebSocket #正经介绍 #WebSocket协议是基于TCP的一种新的HTML5网络协议。它实现了浏览器和服务器全双工(full-duplex)通信----允许服务器主动发送信息给客户端。WebSocket通信协议于2011年被IETF定位标准RFC 6455,并被RFC7936所补充规范 #简单点说 #将客户端和服务器连接在了一起
三、websocket该如何使用呢
import tornado.ioloop import tornado.options import tornado.web from tornado.options import define,options import time import util.ui_methods import util.ui_modules from data.user_modules import User #导入module包 from tornado.web import authenticated from pycket.session import SessionMixin import tornado.websocket import datetime define('port',default=8080,help = 'run port',type=int) class BaseHandler(tornado.web.RequestHandler,SessionMixin): def get_current_user(self): current_user = self.session.get('user') if current_user: return current_user return None class BaseWebSocketHandler(tornado.websocket.WebSocketHandler, SessionMixin): def get_current_user(self): current_user = self.session.get('user') if current_user: return current_user return None class LoginHandler(BaseHandler): def get(self, *args, **kwargs): nextname = self.get_argument('next','') self.render('lesson2.html',nextname = nextname) def post(self, *args, **kwargs): nextname = self.get_argument('next','') user = self.get_argument('name') password = self.get_argument('password','') username =User.by_name(user) if username and password == username[0].password: self.session.set('user',username[0].username) self.redirect(nextname) else: self.render('lesson2.html',nextname=nextname) class IndexHandler(BaseHandler): @authenticated def get(self): self.render('websocket_08.html') class MessageHandler(BaseWebSocketHandler): users = set() def open(self, *args, **kwargs): MessageHandler.users.add(self) for u in self.users: u.write_message( '%s-%s上线了'%( self.current_user, datetime.datetime.now().strftime('%Y-%m-%d%H:%M:%S'), ) ) def on_message(self, message): for u in self.users: #实现先发送内容 u.write_message( '%s-%s说:%s'%( self.current_user, datetime.datetime.now().strftime('%Y-%m-%d%H:%M:%S'), message ) ) def on_close(self): if self in MessageHandler.users: MessageHandler.users.remove(self) for u in self.users: u.write_message( '%s-%s下线了' % ( self.current_user, datetime.datetime.now().strftime('%Y-%m-%d%H:%M:%S'), ) ) application = tornado.web.Application( handlers=[ (r'/login', LoginHandler), (r'/index', IndexHandler), (r'/websocket', MessageHandler), ], template_path = 'templates', static_path= 'static', autoescape = None, ui_methods=util.ui_methods, ui_modules=util.ui_modules, cookie_secret = 'lidang', login_url = '/login', pycket = { 'engine':'redis', 'storage':{ 'host':'localhost', 'port':6379, 'db_sessions':5, 'db_notifications':11, 'max_connections':2 ** 33, }, 'cookie':{ 'expires_days':38, 'max_age':100 } }, debug=True ) if __name__ == '__main__': tornado.options.parse_command_line() http_server = tornado.httpserver.HTTPServer(application) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start()
四、客户端编码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> WebSocket </title> <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet"> <style> *{ margin: 0; padding: 0; } .box{ 800px; margin-left: auto; margin-right: auto; margin-top: 25px; } #text{ 685px; height: 130px; border: 1px solid skyblue; border-radius: 10px; font-size: 20px; text-indent: 1em; resize:none; outline: none; } #text::placeholder{ color: skyblue; } .btn{ 100px; margin: -27px 0 0px 8px; } #messages{ padding-left: 10px; font-size: 25px; } #messages li{ list-style: none; color: #000; line-height: 30px; font-size: 18px; } </style> </head> <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:8080/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> </html>