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第七章笔记

  • 相关阅读:
    call()与apply()的作用与区别
    Tomcat8/9的catalina.out中文乱码问题解决
    怎样查看Jenkins的版本
    每日日报2020.8.18
    528. Random Pick with Weight
    875. Koko Eating Bananas
    721. Accounts Merge
    515. Find Largest Value in Each Tree Row
    286. Walls and Gates (Solution 1)
    408. Valid Word Abbreviation
  • 原文地址:https://www.cnblogs.com/wkhzwmr/p/15581678.html
Copyright © 2011-2022 走看看