Tornado笔记
常用导入的模块
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('')
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!')
前端页面
Run WebSocket
来源于python高校开发实战Django Tornado Flask Twisted第七章笔记