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

原文地址:https://www.cnblogs.com/wkhzwmr/p/15581678.html