博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Twisted网络编程入门
阅读量:6092 次
发布时间:2019-06-20

本文共 3915 字,大约阅读时间需要 13 分钟。

Twisted是用Python实现的基于事件驱动的网络引擎框架,功能非常丰富,基本包括了常用的网络组件。

所谓事件驱动,就是说程序就像是一个报警器(reactor),时刻等待着外部事件(event),诸如有人入侵等,一旦有事件发生,程序就会触发一些特定的操作(callback),注入拨打报警电话等。

Reactor

reactor是twisted框架中的核心,负责管理各种回调函数,接收各种系统事件,并根据规则对事件和回调函数进行匹配、派发处理。在Linux系统中,由于秉承“一切皆文件”的理念,系统中的事件主要就是文件事件以及定时事件。其实大多使用了不同系统中特定的API,具体来说,Linux上默认是epoll,OS X默认是Poll,其他系统默认都是select,每个API都会有一个特定的reactor与之对应。

从代码上来看,每当你import twisted.internet.reactor时,他就会根据当前系统返回特定的reactor module(twisted/twisted/internet/default.py),然后调用特定reactor module的install()函数。这里我们看一下对应Linux系统的epollreactor的install函数

# twisted/twisted/internet/epollreactor.pydef install():    """    Install the epoll() reactor.    """    p = EPollReactor()    from twisted.internet.main import installReactor    installReactor(p)#twisted/twisted/intenet/main.pydef installReactor(reactor):    """    Install reactor C{reactor}.    @param reactor: An object that provides one or more IReactor* interfaces.    """    # this stuff should be common to all reactors.    import twisted.internet    import sys    if 'twisted.internet.reactor' in sys.modules:        raise error.ReactorAlreadyInstalledError("reactor already installed")    twisted.internet.reactor = reactor    sys.modules['twisted.internet.reactor'] = reactor

代码是非常清楚的,就是创建了一个EPollReactor的实例,然后使用sys.module[""] = reactor将其注册为默认的reactor,这也就是使用twisted编程时不需显示创建reactor的原因。

究竟一个reactor到底干了些什么呢?twisted在这一块为了抽象以及扩展性,写了大量的类,用了大量的继承,但是简单来说,最终会落回到EPollReactor的doPoll函数中。

def doPoll(self, timeout):        """        Poll the poller for new events.        """        if timeout is None:            timeout = -1  # Wait indefinitely.        try:            # Limit the number of events to the number of io objects we're            # currently tracking (because that's maybe a good heuristic) and            # the amount of time we block to the value specified by our            # caller.            l = self._poller.poll(timeout, len(self._selectables))        except IOError as err:            if err.errno == errno.EINTR:                return            # See epoll_wait(2) for documentation on the other conditions            # under which this can fail.  They can only be due to a serious            # programming error on our part, so let's just announce them            # loudly.            raise        _drdw = self._doReadOrWrite        for fd, event in l:            try:                selectable = self._selectables[fd]            except KeyError:                pass            else:                log.callWithLogger(selectable, _drdw, selectable, fd, event)

  其中的self._poller通过epoll就是一个epoll调用的返回值,简单点说,也就是一个典型的epoll应用场景,在timeout时间内,检查需要处理的事件,然后通过log.callWithLogger调用相关的回调函数。

Transport

用于抽象通信双方之间的链接(TCP、UDP等),通过它可以向对方发送数据,获取对方信息等。

Protocol

用于抽象双方的通信协议,包括如何建立链接、处理数据以及出错处理等接口。一个类实现了这些接口,就等于定义了一个新的协议,twisted自带的协议非常多,一般情况下不需要自定义协议,除非你有特殊要求。

Protocol Factory

熟悉设计模式的应该对factory不陌生,简单来说,这个类定义了一个接口buildProtocol,用于返回一个Protocl实例(但是通常的做法是在factory类中使用类成员protocol来注册响应的Protocol),同时在这个类里你可以保存一些数据,用于配置或者管理系统中所有的Protocol实例。

 

简单的Echo服务器程序

# Serverfrom twisted.internet import protocol, reactorclass Echo(protocol.Protocol):    def dataReceived(self, data):        self.transport.write(data)class EchoFactory(protocol.Factory):    def buildProtocol(self, addr):        return Echo()reactor.listenTCP(8080, EchoFactory())reactor.run()# Clientfrom twisted.internet import protocol, reactorclass EchoClient(protocol.Protocol):    def connectionMade(self):        self.transport.write("Hello, world!")    def dataReceived(self, data):        self.transport.loseConnection()class EchoFactory(protocol.ClientFactory):    def buildProtocol(self, addr):        return EchoClient()    def clientConnectionFailed(self, connector, reason):        reactor.stop()    def clientConnectionLost(self, connector, reason):        reactor.stop()reactor.connectTCP("localhost", 8080, EchoFactory())reactor.run()

  

  

转载于:https://www.cnblogs.com/jimmychange/p/3508041.html

你可能感兴趣的文章
源码分析MySQL mysql_real_query函数
查看>>
求职简历撰写要点
查看>>
第七章LED将为我闪烁:控制发光二极管
查看>>
Windows 进程间通信
查看>>
预处理、const与sizeof相关面试题
查看>>
爬虫豆瓣top250项目-开发文档
查看>>
Elasticsearch增删改查
查看>>
oracle归档日志增长过快处理方法
查看>>
有趣的数学书籍
查看>>
teamviewer 卸载干净
查看>>
多线程设计模式
查看>>
解读自定义UICollectionViewLayout--感动了我自己
查看>>
CCF201612-1 中间数(解法二)(100分)
查看>>
SqlServer作业指定目标服务器
查看>>
UnrealEngine4.5 BluePrint初始化中遇到编译警告的解决办法
查看>>
User implements HttpSessionBindingListener
查看>>
抽象工厂方法
查看>>
ubuntu apt-get 安装 lnmp
查看>>
PHP下使用Redis消息队列发布微博
查看>>
焊盘 往同一个方向增加 固定的长度方法 总结
查看>>