zoukankan      html  css  js  c++  java
  • Twisted

    Twisted定义

        Twisted是一个基于事件驱动的网络引擎框架

         网络框架,别人预先定义好的一个框架(一个项目),如.net某个web框架有25个class,从BeginRequest依次执行类里的process方法,程序员自己定义一个类,添加到框架里,应用程序从上到下运行,就会执行自定义代码。框架只知道这个类的列表,不关心你写了什么内容,从上到下执行,类似于一个执行链,C#里叫委托链。也就是把代码类放到这个列表中,委托这个框架替你执行。

        事件驱动(not event),把自定义代码注册到框架中,框架代替你执行。或者框架提供几个接口,让你插入数据(python里没有 )。

        委托不能为空,事件可以为空。

    演示一个最简单的框架

    前期准备:

         新建一个名为event_drive的python package,里面新建一个event_drive.py文件,这个就是框架主文件,把package目录复制到sys.path中,如:c:python27libsite-package

    event_drive.py:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    event_list = []    #[myclass,]
     
    def run():
        for event in event_list:
            obj = event()
            obj.execute()
     
    class BaseHandler(object):
        """
        用户必须继承该类,从而规范所有类的方法(类似于接口的功能)
        """
        def execute(self):
            raise Exception('you must overwrite execute')
    自定义代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    from event_drive import event_drive
     
    class MyClass(event_drive.BaseHandler):
     
        def execute(self):  #重写execute方法
            print "执行了自定义execute方法"
     
    event_drive.event_list.append(MyClass)  #注册到委托链即“注册一个事件”
    event_drive.run()
    执行过程:    
    1. 导入event_drive文件夹中的event_drive文件

    2. 自定义一个类MyClass,这个类继承了event_drive文件中BaseHandler类

    3. 类里实现execute方法,内容无所谓甚至可以为空,方法名称execute不能改变

    4. 注册事件到框架的委托链,即把类名list.append(MyClass)传进去(下面的Twisted框架是创建对象后改一个字段为类名也是同样的目的)

    5. 执行run方法,框架自己就把MyClass中的方法执行了

    执行结果:
    1
    2
    执行了自定义execute方法
    Process finished with exit code 0

    Twisted框架:以socket为例

    安装Twisted:(linux参考如下,windows直接用安装包)

    1
    2
    3
    cd Twisted-15.5.0
    python setup.py build
    python setup.py install

        ps:twisted调用了zope和win32api模块,先安装这两个,要不会报错。

    Twisted_server.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from twisted.internet import reactor, protocol
    from twisted.web.client import getPage
    from twisted.internet import reactor
    import time
     
    class Echo(protocol.Protocol):    #继承protocol.py中的Protocol类
     
        def dataReceived(self, data):    
            self.transport.write(data)    #将收到的内容直接发送回去
     
    factory = protocol.ServerFactory()    #实例化
    factory.protocol = Echo    #将自定义类传给对象
     
    reactor.listenTCP(8000,factory)    #将端口和实例化对象作为参数传给reactor
    reactor.run()
    Twisted_client.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import socket
    ip_port=('127.0.0.1',8000)
    sk=socket.socket()
    sk.connect(ip_port)
    sk.settimeout(5)
     
    while True:
        inp=raw_input("please input:")
        sk.sendall(inp)
        print sk.recv(1024)
     
    sk.close()

    执行原理

        跟SocketServer原理类似,内部封装,内部有一个while循环,while循环一旦触发,找到这个类,执行这个类的构造方法,创建对象,通过对象,执行预定义的方法,

    源码分析


    程序执行流程:

    • 运行服务端程序
    • 创建Protocol的派生类Echo

          解释:自定义Echo类,名字随便起,它继承了Protocol类,Protocol类又继承了BaseProtocol类,有了最左边的图

    • 创建ServerFactory对象,并将Echo类封装到其protocol字段

          解释:ServerSocket是将MyClass以参数的形式封装,这个是以字段的形式

    • 执行reactor的 listenTCP 方法,内部使用 tcp.Port 创建socket server对象,并将该对象添加到了 reactor的set类型的字段 _read 中

          解释:

      1. print type(reactor)
      2. ==>
      3. <class 'twisted.internet.selectreactor.SelectReactor'>

      去selectreactor.SelectReactor中找listenTCP,看上面的类继承关系图,继承了好多类。listenTCP和run方法都在基类里。

      1. def listenTCP(self, port, factory, backlog=50, interface=''):
      2. p = tcp.Port(port, factory, backlog, interface, self)
      3. p.startListening()
      4. return p
      其中把factory对象传入,就相当于:
          1、把Echo类封装到factory字段
          2、再把factory对象封装到listenTCP
          3、tcp.port里创建了socket连接
    • 执行reactor的 run 方法,内部执行 while 循环,并通过 select 来监视 _read 中文件描述符是否有变化,循环中...

        解释:SelectReactor中包含两个集合_reads=set()和_writes=set(),不允许重复的集合,有连接后把文件句柄添加到这个集合中。开始执行reactor.run(),它调用基类里的mainLoop方法,又调取的selectreactor.doInteration,找不到?因为它是个重命名doInteration=doSelect,这个方法里面调取的就是select方法,通过调用select,循环这个_reads。一旦有句柄进来,通过反射去_reads里找“doRead”执行方法。

    • 客户端请求到达

             解释:可以通过debug方式了解调用顺序

    • 执行reactor的 _doReadOrWrite 方法,其内部通过反射调用 tcp.Port 类的 doRead 方法,内部 accept 客户端连接并创建Server对象实例(用于封装客户端socket信息)和 创建 Echo 对象实例(用于处理请求) ,然后调用 Echo 对象实例的 makeConnection 方法,创建连接。
    • 执行 tcp.Server 类的 doRead 方法,读取数据,
    • 执行 tcp.Server 类的 _dataReceived 方法,如果读取数据内容为空(关闭链接),否则,触发Echo 的 dataReceived 方法
    • 执行 Echo 的 dataReceived 方法

        Twisted主要用于网络操作,它支持许多常见的传输及应用层协议,包括TCP、UDP、SSL/TLS、HTTP、IMAP、SSH、IRC以及FTP。其中包含了诸多功能,例如:网络协议、线程、数据库管理、网络操作、电子邮件等。

    优点

    • 使用基于事件驱动的编程模型,而不是多线程模型。

    • 跨平台:为主流操作系统平台暴露出的事件通知系统提供统一的接口。

    • “内置电池”的能力:提供流行的应用层协议实现,因此Twisted马上就可为开发人员所用。

    • 符合RFC规范,已经通过健壮的测试套件证明了其一致性。

    • 能很容易的配合多个网络协议一起使用。

    • 可扩展。

    一个非常全面介绍Twisted网站

        http://twisted.readthedocs.org/en/twisted-15.5.0/
















  • 相关阅读:
    《Rubu基础教程第五版》第一章笔记
    《Linux Command Line and Shell Scripting Bible》Part 14 处理用户输入
    Phpstorm-Xdebug配置
    Phpstorm-svn配置
    Phpstorm-sftp配置
    3前端案例-遮罩
    2前端案例-选项卡样式
    1前端案例-tag标签+随机位置
    Phpstorm-php在线手册配置
    mysql语句总结
  • 原文地址:https://www.cnblogs.com/daliangtou/p/5091226.html
Copyright © 2011-2022 走看看