zoukankan      html  css  js  c++  java
  • Tornado笔记

    tornado是什么,Tornado是个使用Python编写的一个强大的可扩展的Web服务器,通常被用作大型站点的接口服务框架。而Django是部署大型完整的网站。
    使用tornado.ioloop启动

    常用导入的模块

    import tornado.web
    import tornado.ioloop
    

    模块中主要作用的类

    创建 Web 应用程序的子类,以及各种支持类

    tornado.web.RequestHandler
    

    启动服务器

    tornado.ioloop
    tornado.ioloop.IOLoop.current().start() 
    

    IOLoop是Tornado的主时间循环对象,Tornado程序通过它监听外部客户端的访问请求,并执行相应的操作。

    调试模式

    在linux平台上是ctrl+c捕捉终止运行,在windows平台是ctrl+pause

    import tornado.ioloop
    import tornado.web
    
    def make_app():
        return tornado.web.Application([
            # 此处填写映射路由,d
        ],debug=True) # 自动加载调试模式
    
    def main():
        app = make_app() # 建立Application对象
        app.listen(8888)
        # ctrl+c退出机制
        try:
            tornado.ioloop.IOLoop.current().start()
        except KeyboardInterrupt: # 
            tornado.ioloop.IOLoop.current().stop()
        print('Program exit!')
    
    
    main()
    

    基础案例

    import tornado.ioloop
    import tornado.web
    
    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            self.write("Hello world1")
    
    def make_app():
        return tornado.web.Application([
            (r"/index", MainHandler), # 页面处理函数
            # 利用正则传入
            (r"/entry/11/([0-9]+)", EntryHandler), # ([^/]+)
        ],
        debug=True)
    
    class EntryHandler(tornado.web.RequestHandler):
        def get(self, slug1):
            # slug1 = '不定义直接写在函数的参数中输出怎么可能有' # 这是url参数的传入
            self.write(slug1)
    
    def main():
        app = make_app()
        app.listen(8888)
        try:
            tornado.ioloop.IOLoop.current().start()
        except KeyboardInterrupt:
            tornado.ioloop.IOLoop.current().stop()
        print("killed")
    
    if __name__ == "__main__":
        main()
    

    异步化

    import tornado.ioloop
    import tornado.web
    import tornado.httpclient
    
    class MainHandler(tornado.web.RequestHandler):
        @tornado.web.asynchronous 
        def get(self):
            http = tornado.httpclient.AsyncHTTPClient()
            http.fetch("http://www.baidu.com", # 这竟然是重定向
            # callback=self.on_response先被执行,再执行这一条语句
                       callback=self.on_response)
    
        def on_response(self, response):
            if response.error: raise tornado.web.HTTPError(500)
            self.write(response.body)
            self.finish()
    
    
    def make_app():
        return tornado.web.Application([
            (r"/", MainHandler),
        ])
    
    def main():
        app = make_app()
        app.listen(8888)
        tornado.ioloop.IOLoop.current().start()
    
    if __name__ == "__main__":
        main()
    

    协程化

    import tornado.ioloop
    import tornado.web
    import tornado.httpclient
    
    # 协程化
    class MainHandler(tornado.web.RequestHandler):
        @tornado.gen.coroutine # 协程化这个比异步化慢一点
        def get(self):
            http = tornado.httpclient.AsyncHTTPClient() # 异步对象耗时处理
            response = yield http.fetch("http://www.baidu.com") # yeild关键字获取异步对象的处理结果
            self.write(response.body)
    
    
    def make_app():
        return tornado.web.Application([
            (r"/", MainHandler),
        ])
    
    def main():
        app = make_app()
        app.listen(8888)
        tornado.ioloop.IOLoop.current().start()
    
    if __name__ == "__main__":
        main()
    

    安全机制cookie

    import tornado.web
    import tornado.ioloop
    
    session_id = 1
    
    
    
    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            global session_id
            if not self.get_secure_cookie("session"): # 读取cookie使用了get_secure_cookie替代原来的get_cookie
                self.set_secure_cookie("session",str(session_id)) # 写入cookie使用set_secure_cookie替代原来的set_cookie
                session_id = session_id + 1
                self.write("Your session got a new session!")
            else:
                self.write("Your session was set!") # 写入到页面中
    
    application = tornado.web.Application([
        (r"/", MainHandler),
    ], cookie_secret="SECRET_DONT_LEAK") # 这玩意加密cookie,并把cookie保存在客户端
    
    def main():
        application.listen(8888)
        tornado.ioloop.IOLoop.current().start()
    
    if __name__ == "__main__":
        main()
    

    用户身份认证

    完整的身份认证编程框架

    无法进入主页面,一直在注册,报错Cannot redirect after headers have been written

    import tornado.web
    import tornado.ioloop
    import uuid
    
    dict_sessions = {}
    class BaseHandler(tornado.web.RequestHandler):
        def get_current_user(self): # 重载current_user函数
            session_id = self.get_secure_cookie("session_id")
            return dict_sessions.get(session_id) # 会话id从dict_sessions中获取用户名并返回
    
    
    class MainHandler(BaseHandler):
        @tornado.web.authenticated  # 需要身份认证才能访问的处理器
        def get(self):
            if not self.current_user: # 根据current)user是否被赋值来判断用户的身份认证
                self.redirect("/login")
                return
            name = tornado.escape.xhtml_escape(self.current_user) # 获取登陆框中输入的名字
            self.write("Hello, " + name)
    
    class LoginHandler(BaseHandler):
        def get(self): # 登录界面
            self.write('<html><body><form action="/login" method="post">'
                       'Name: <input type="text" name="name">'
                       '<input type="submit" value="Sign in">'
                       '</form></body></html>')
    
        def post(self): # 验证是否允许登录
            if len(self.get_argument("name"))<3: # 这是啥
                self.redirect("/login")
            session_id = str(uuid.uuid1())
            dict_sessions[session_id] = self.get_argument("name")
            self.set_secure_cookie("session_id", session_id)
            self.redirect("/") # 重定向
    
    application = tornado.web.Application([
        (r"/", MainHandler),
        (r"/login", LoginHandler),
    ], cookie_secret="SECRET_DONT_LEAK") # 定义cookie加密密钥
    
    
    def main():
        application.listen(8888)
        tornado.ioloop.IOLoop.current().start() # 挂起监听
        
    
    if __name__ == "__main__":
        main()
    

    WebSocket简介

    一、特性

    1.全双工通信
    2.实时通信
    3.适合服务器端主动推送的场景

    二、实现原理

    通信原理
    是在客户端与服务器之间建立TCP持久链接,从而使得当服务器有消息要推送给客户端时能够进行及时通信。
    实现过程
    客户端发送的HTTP Request包中有告知服务器需要建立一个WebSocket长链接信道
    服务端如果同意建立Websocket链接则返回带有WebSocket相关信息的Response

    tornado实现websocket

    tornado定义的tornado.websocket.WebSocketHandler类

    该类中的函数主要用来处理WebSocket链接的请求
    以下均自动调用(不用编写逻辑函数,直接按格式写)
    open()函数:
    on_message(message)函数
    on_close()函数:

    write_message(message,binary=False)

    用于相与本链接相对应的客户端写消息

    close(code=None,reason=None)函数

    主动关闭WebSocket连接。其中的code和reason用于告诉客户端链接被关闭的原因。
    code参数必须是一个数值,而reason是一个字符串。

    实现案例

    开启一个单独的线程,不断向页面实时的发送时间

    import tornado.ioloop
    import tornado.web
    import tornado.websocket
    ## Websocket
    from tornado.options import define, options, parse_command_line
    
    define("port", default=8888, help="run on the given port", type=int)
    
    clients = dict()	# 全局字典的定义,保存登录用户的信息
    
    class IndexHandler(tornado.web.RequestHandler):
        @tornado.web.asynchronous
        def get(self):
            self.render("index.html") # 页面处理器
    
    class MyWebSocketHandler(tornado.websocket.WebSocketHandler):
        def open(self, *args):							#有新链接是被调用
            self.id = self.get_argument("Id")
            self.stream.set_nodelay(True)
            # 保存用户名的键值对
            clients[self.id] = {"id": self.id, "object": self}		#保存Session到clients字典
    
        def on_message(self, message):        			#收到消息时被调用
            print("Client %s received a message : %s" % (self.id, message))
            
        def on_close(self):							#关闭连接时被调用
            if self.id in clients:
                del clients[self.id]
                
                print("Client %s is closed" % (self.id))
    
        def check_origin(self, origin):
            return True
    
    app = tornado.web.Application([
        (r'/', IndexHandler),
        (r'/websocket', MyWebSocketHandler),
    ])
    
    import threading
    import time
    
    #启动单独的线程运行此函数,每隔1秒钟向所有的客户端推送当前时间
    def sendTime():		# 只允许一个客户端连接,另一个客户端不允许连接,它是一种身份验证,所以另外的客户端不允许连接						
        import datetime
        while True:  # 启动这个还无法中断,我是指从终端终端这个Tornado服务器
            for key in clients.keys():
                msg = str(datetime.datetime.now())
                clients[key]["object"].write_message(msg)
                print("write to client %s: %s" % (key,msg)) # 这里的key就是客户端的session,也是id
            time.sleep(1)
    
      
    if __name__ == '__main__':
        threading.Thread(target=sendTime).start()			#启动推送时间线程
        parse_command_line() # 这个函数不知
        app.listen(options.port) # define中填写port是干慢
        try:
            tornado.ioloop.IOLoop.current().start()
        except KeyboardInterrupt: # 在linux平台上是ctrl+c捕捉终止运行,在windows平台是ctrl+pause
            tornado.ioloop.IOLoop.current().stop()
        print('Program exit!')
    

    前端页面

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
    	
        </head>
        <body>
            <a href="javascript:WebSocketTest()">Run WebSocket</a>
            <div id="messages" style="height:300px;background:black;color:white;"></div>
        </body>
    	
        <script type="text/javascript">
            var messageContainer = document.getElementById("messages");
            function WebSocketTest() {
                if ("WebSocket" in window) {
                    messageContainer.innerHTML = "WebSocket is supported by your Browser!";
                    var ws = new WebSocket("ws://localhost:8888/websocket?Id=123456789");
                    ws.onopen = function() {
                        ws.send("Message to send");
                    };
                    ws.onmessage = function (evt) { 
                        var received_msg = evt.data;
                        messageContainer.innerHTML = messageContainer.innerHTML+"<br/>Message is received:"+received_msg;
                    };
                    ws.onclose = function() { 
                        messageContainer.innerHTML = messageContainer.innerHTML+"<br/>Connection is closed...";
                    };
                } else {
                    messageContainer.innerHTML = "WebSocket NOT supported by your Browser!";
                }
            }
        </script>
    </html>
    

    来源于python高校开发实战Django Tornado Flask Twisted第七章笔记

  • 相关阅读:
    强连通分量(Kosaraju)
    拓扑排序
    树状数组BIT
    差分
    RMQ(ST表)
    LCA(Tarjan)
    LCA(ST倍增)
    海亮SC2019 树上数数(转载)
    海亮SC
    【十二省联考2019】异或粽子/可持久化01trie
  • 原文地址:https://www.cnblogs.com/wkhzwmr/p/15581678.html
Copyright © 2011-2022 走看看