python学习:python网络框架Tornado(2):拓展和websocket
Tornado拓展内容
通过Tornado的tonado.web.RequestHandler类提供的hook,我们可以拓展Handler(Django视图函数)的处理内容。
RequestHandler类源代码:
def _initialize(self) -> None: pass initialize = _initialize # type: Callable[..., None] """Hook for subclass initialization. Called for each request. A dictionary passed as the third argument of a ``URLSpec`` will be supplied as keyword arguments to ``initialize()``. Example:: class ProfileHandler(RequestHandler): def initialize(self, database): self.database = database def get(self, username): ... app = Application([ (r'/user/(.*)', ProfileHandler, dict(database=database)), ]) """
拓展实现示例:
#单继承方式 class ParentHandler(tornado.web.RequestHandler): def initialize(self): #添加额外内容 self.A = 'hello' #调用父类的initialize方法 super(ParentHandler,self).initialize() class SingleHandler(ParentHandler): def get(self): print(self.A) self.write("welcome")
#多继承方式 class OneParentHandler(object): def initialize(self): #添加额外内容 self.A = "hello1" #调用自己initialize() super(OneParentHandler,self).initialize() class MultiHandler(OneParentHandler,tornado.web.RequestHandler): def get(self): print(self.A) self.write("welcome1") 可以通过单继承和多继承两种方式拓展RequestHandler功能。 类调用方式补充: #类对象调用方式 class Parent(object): def sayHi(self): print("parent hi") class Childen(Parent): def sayHi(self): print("child hi") #调用父类的方法 super(Childen,self).sayHi() super().sayHi() if __name__ == "__main__": #创建类对象 chi = Childen() #使用对象直接调用类方法 #自动将对象传入类方法 chi.sayHi() #使用类调用类方法,将对象传入 Childen.sayHi(chi) 使用拓展实现自定义Session: #自定义Session组件 #保存session信息,保存在内存 container ={} #session处理类 #生成随机字符串,session_id #设置用户cookie #session持久化 class Sessions(): def __init__(self,handler): #将handler传入,可以调用RequestHandler的set_cookie方法 self.handler = handler # 生成随机字符串,session_id self.session_id = None #获取用户提交session_id request_session_id = self.handler.get_cookie("session_id") #没有session_id,第一次登陆 if not request_session_id : self.session_id = self.get_random_str() container[self.session_id] = {} else: #用户传过来session_id是否正确 if request_session_id in container: self.session_id = request_session_id else: #不正确,创建新的session_id self.session_id = self.get_random_str() container[self.session_id] = {} #将session_id的cookie设置回客户端 self.handler.set_cookie("session_id",self.session_id) #设置session键值 def __setitem__(self, key, value): print("setitem:",key,value) container[self.session_id][key]=value #获取session键值 def __getitem__(self, item): return container[self.session_id].get(item) #删除session键值 def __delitem__(self, key): del container[self.session_id][key] #清空用户session def clear(self): #设置为{} container[self.session_id] = {} #直接将session键值删除 # del container[self.session_id] #生成随机字符串 def get_random_str(self): import hashlib import time var_time = str(time.time()) m = hashlib.md5() m.update(bytes(var_time,encoding="utf-8")) return m.hexdigest() #父类继承RequestHandler,拓展initialize方法 class ParentHandler(tornado.web.RequestHandler): def initialize(self): #生成随机字符串,session_id键 #设置字典值给session_id self.session = Sessions(self) #调用父类initailize()方法 super().initialize() #单继承方式, class SessionHandler(ParentHandler): def get(self): self.render("session.html") def post(self): # 设置session # self.session["key"] = value,这种方式直接调用类的__setitem__方法 #del self.session["key"],调用__delitem__方法 user = self.get_argument("user") pwd = self.get_argument("pwd") if user == "root" and pwd == "123": #设置session print("session:",user,pwd) self.session["name"] = user self.session["pwd"] = pwd self.redirect("/home") else: self.redirect("www.baidu.com") #可以跳转到home页面,通过session获取数据 class HomeHandler(ParentHandler): def get(self): user = self.session["name"] self.render("home.html",user =user)
WebSocket实现解析
Http协议,实现短链接,浏览器请求即断开,服务器返回响应,单向;
WebSocket,socket协议实现长轮询,双工通道,发送信息后,不断开;服务器可以推送群体信息;
1Socket分析
服务端启动socket,监听ip地址和端口;
服务端等待客户端链接;
客户端连接服务端,浏览器创建链接,发起链接请求,服务端同意链接,链接建立成功;
链接过程:客户端发送生成的特殊字符串,服务端接收字符串将字符串处理,利用magic string加密,magic string是一段固定字符串。服务端将加密值发送到客户端。客户端使用Websocket加密方式加密字符串,和服务端发回字符串比较,是否是使用同样协议。
客户端发送信息到服务端,客户端接收服务端信息;
服务端发送信息到客户端,服务端接收客户端信息;
服务端过程模拟:
sever1.py
#服务端 #socket import socket #获取网络socket,SOCK_STREAM:使用TCP协议 s1=socket.socket(socket.AF_INET,socket.SOCK_STREAM); #绑定端口 s1.bind(("127.0.0.1",8000)); #监听连接数 s1.listen(5) #监听连接,在这里一直停住,等待链接 con,addr=s1.accept() #获取客户端发送的握手消息 data=con.recv(8096) #通过magic string,使用sha1加密,返回 #获取data中的随机字符串,查找data中Sec-WebSocket-key #解析data过程略,将随机字符串加上一段固定字符串magic string sec_websocket_key = "" + "magic string" #使用sha1加密 import hashlib import base64 websocket_str = base64.b64encode(hashlib.sha1(sec_websocket_key.encode("utf-8")).digest()) #根据data返回格式,将加密字符串设置给Sec-WebScocket-key,返回给客户端 response_str = "otherinfo;Sec-WebSocket-key:%s" %(websocket_str) con.send(bytes(response_str,encoding="utf-8"))
浏览器客户端访问html页面:
client.html文件内容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>客户端</title> <script> //浏览器封装操作,生成特殊字符串,发送请求链接 ws = new WebSocket("ws:127.0.0.1:8000") //判断是否链接成功,链接成功执行onopen() ws.onopen=function(){ alert("链接成功") } </script> </head> <body> <h1>websocket</h1> </body> </html>
Tornado的WebSocket使用
Tornado中使用对应handler继承tornado.websocket.WebSocketHandler进行收发信息。
示例:
#Tornado的WebSocket import tornado.websocket class WebSocketHandler(tornado.websocket.WebSocketHandler): # 服务端建立链接,执行open方法 def open(self, *args: str, **kwargs: str): print("链接成功") def on_message(self, message): print(message) #服务端发送返回信息 self.write_message(message)
对应浏览器的html页面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>websocket</title> <script> //浏览器封装操作,生成特殊字符串,发送请求链接 ws = new WebSocket("ws:127.0.0.1:8000") //判断是否链接成功,链接成功执行onopen() ws.onopen=function(){ alert("链接成功") //发送信息, ws.send("hello") } //监听返回信息 ws.onmessage=function(event){ alert(event.data) } </script> </head> <body></body> </html>
本文来自博客园,作者:渔歌晚唱,转载请注明原文链接:https://www.cnblogs.com/tangToms/articles/14174645.html

浙公网安备 33010602011771号