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>

 

posted @ 2020-12-22 18:57  渔歌晚唱  阅读(275)  评论(0)    收藏  举报