Twisted源码分析1

来源:互联网 发布:淘宝三颗心多少信誉 编辑:程序博客网 时间:2024/05/17 01:55

Twisted是用python编写的事件驱动的网络框架,虽然Twisted从发布到现在已经有不少年头了,而且现在也出现了不少新的高性能异步I/O框架,比如说tornado,但是Twisted任然具有很好的学习价值。如果想要看Twisted的教程的话,Twisted有着非常好的教程Twisted introduction,这个是翻译


现在进入正题

我们通过一个简单的例子来开始我们的分析

<code class="hljs python has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> twisted.internet.protocol <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> ServerFactory, Protocol<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">PoetryProtocol</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(Protocol)</span>:</span>    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">connectionMade</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self)</span>:</span>        self.transport.write(self.factory.poem)        self.transport.loseConnection()<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">PoetryFactory</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(ServerFactory)</span>:</span>    protocol = PoetryProtocol    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">__init__</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, poem)</span>:</span>        self.poem = poem<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">main</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">()</span>:</span>    options, poetry_file = parse_args()    poem = open(poetry_file).read()    factory = PoetryFactory(poem)    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> twisted.internet <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> reactor    port = reactor.listenTCP(options.port <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">or</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, factory,                             interface=options.iface)    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">print</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'Serving %s on %s.'</span> % (poetry_file, port.getHost())    reactor.run()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li></ul>

排版需要,这里仅仅列出一部分代码,全部代码详见这里 
这是一个非常简单的服务器,每当有客户端连接时,就向客户端发送一首诗歌的全部内容,然后断开连接,在这里我们仅仅关注reactor。reactor是事件循环管理器,用于注册,运行,销毁事件,以及当事件发生时调用回调函数。我们需要注意,reactor循环是在主进程中运行,也就是调用reactor.run()的进程中运行,一但循环开始运行,就会一直运行下去,知道调用reactor.stop()方法停止。在Twisted中,reactor是单例模式,当你首次导入reactor模块的时候就会创建它,接下来你在应用中的其他地方导入reactor时将返回第一次创建的对象

<code class="hljs python has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> twisted.internet <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> reactor</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

上面引入的方式是Twisted的默认方法,然我们来看看这段代码是如何实现单例模式的

<code class="hljs python has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># /twisted/internet/reactor.py</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> __future__ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> division, absolute_import<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> sys<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">del</span> sys.modules[<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'twisted.internet.reactor'</span>]<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> twisted.internet <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> defaultdefault.install()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

当第一次导入时,首先删除模块字典中的“twisted.internet.reactor”的值(如果它存在的话),然后安装默认的reactor。sys.modules是一个模块名和模块对象匹配的全局字典,当import一个模块时会检查这个字典,如果加载了只是将模块的名字加入到导入该模块的模块的命名空间中,如果没有加载就从sys.path目录中按照模块名称查找模块文件,然后将模块导入内存,将模块名和模块对象映射加入到字典中,在将名称导入到导入该模块的模块的命名空间中,那么default.py中代码为:

<code class="hljs python has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># /twisted/internet/default.py</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> __future__ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> division, absolute_import__all__ = [<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"install"</span>]<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> twisted.python.runtime <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> platform<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">_getInstallFunction</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(platform)</span>:</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>:        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> platform.isLinux():            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>:                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> twisted.internet.epollreactor <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> install            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">except</span> ImportError:                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> twisted.internet.pollreactor <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> install        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">elif</span> platform.getType() == <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'posix'</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span> platform.isMacOSX():            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> twisted.internet.pollreactor <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> install        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>:            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> twisted.internet.selectreactor <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> install    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">except</span> ImportError:        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> twisted.internet.selectreactor <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> install    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> installinstall = _getInstallFunction(platform)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li></ul>

这里会根据平台来选择相应的reactor,如果在linux下优先使用epollreactor,如果抛出异常那么使用pollreactor或者是selectreactor,如果是windows则使用selectreactor。我们在这里研究pollreactor

<code class="hljs python has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># /twisted/internet/pollreactor.py</span><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">install</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">()</span>:</span>    <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"""Install the poll() reactor."""</span>    p = PollReactor()    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">from</span> twisted.internet.main <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> installReactor    installReactor(p)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># /twisted/internet/main.py</span><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">installReactor</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(reactor)</span>:</span>    <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"""    Install reactor C{reactor}.    @param reactor: An object that provides one or more IReactor* interfaces.    """</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># this stuff should be common to all reactors.</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> twisted.internet    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> sys    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'twisted.internet.reactor'</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> sys.modules:        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">raise</span> error.ReactorAlreadyInstalledError(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"reactor already installed"</span>)    twisted.internet.reactor = reactor    sys.modules[<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'twisted.internet.reactor'</span>] = reactor</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>

在这里,将reactor赋值给twisted.internet.reactor对象,并且将reactor对象赋给模块字典的“twisted.internet.reactor”键,以后再导入reactor,就会导入这个单例了

<code class="hljs python has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># /twisted/internet/pollreactor.py</span><span class="hljs-decorator" style="color: rgb(0, 102, 102); box-sizing: border-box;">@implementer(IReactorFDSet)</span><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">PollReactor</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(posixbase.PosixReactorBase, posixbase._PollLikeMixin)</span>:</span>    _POLL_DISCONNECTED = (POLLHUP | POLLERR | POLLNVAL)    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># POLLHUP 连接挂起</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># POLLNVAL 非法请求:文件描述符无法打开</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># POLLERR 连接出现错误</span>    _POLL_IN = POLLIN <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 代表有数据可读</span>    _POLL_OUT = POLLOUT <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 代表有数据可写,并且没有阻塞</span>    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">__init__</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self)</span>:</span>        <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"""        初始化polling对象,文件描述符追踪字典,以及基类        """</span>        self._poller = poll() <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># poll调用</span>        self._selectables = {}        self._reads = {}        self._writes = {}        posixbase.PosixReactorBase.__init__(self)    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">_updateRegistration</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, fd)</span>:</span>        <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"""        更新polling对象对文件描述符状态的追踪        """</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>:            self._poller.unregister(fd)            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 移除被polling对象追踪的文件描述符</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">except</span> KeyError:            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">pass</span>        mask = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> fd <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> self._reads:            mask = mask | POLLIN        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> fd <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> self._writes:            mask = mask | POLLOUT        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> mask != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>:            self._poller.register(fd, mask)         <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>:            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> fd <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> self._selectables:                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">del</span> self._selectables[fd]    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">_dictRemove</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, selectable, mdict)</span>:</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>:            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># the easy way</span>            fd = selectable.fileno()            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 确保文件描述符是真实的</span>            mdict[fd]        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">except</span>:            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> fd, fdes <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> self._selectables.items():                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> selectable <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> fdes:                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>:                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> fd <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> mdict:            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">del</span> mdict[fd]            self._updateRegistration(fd)    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">addReader</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, reader)</span>:</span>        fd = reader.fileno()        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> fd <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> self._reads:            self._selectables[fd] = reader            self._reads[fd] =  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>            self._updateRegistration(fd)    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">addWriter</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, writer)</span>:</span>        <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"""Add a FileDescriptor for notification of data available to write.        """</span>        fd = writer.fileno()        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> fd <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> self._writes:            self._selectables[fd] = writer            self._writes[fd] =  <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>            self._updateRegistration(fd)    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">removeReader</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, reader)</span>:</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> self._dictRemove(reader, self._reads)    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">removeWriter</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, writer)</span>:</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> self._dictRemove(writer, self._writes)    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">removeAll</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self)</span>:</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> self._removeAll(            [self._selectables[fd] <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> fd <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> self._reads],            [self._selectables[fd] <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> fd <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> self._writes])    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 这里是重点</span>    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">doPoll</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, timeout)</span>:</span>        <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"""Poll the poller for new events."""</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> timeout <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">None</span>:            timeout = int(timeout * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span>) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># convert seconds to milliseconds</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>:            l = self._poller.poll(timeout)            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 返回一组可能为空的文件描述符-事件二元组,文件描</span>            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 述符代表当前有事件发生的socket对象,event代表</span>            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 事件的种类,可能为上面定义的POLLIN,POLLOUT等</span>            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 中的一种</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">except</span> SelectError <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> e:            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> e.args[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] == errno.EINTR:                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 系统调用被打断</span>                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>:                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 直接抛出异常</span>                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">raise</span>        _drdw = self._doReadOrWrite        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> fd, event <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> l:            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>:                selectable = self._selectables[fd]            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">except</span> KeyError:                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">continue</span>            log.callWithLogger(selectable, _drdw, selectable, fd, event)    doIteration = doPoll <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 会被mainloop函数调用,实现事务监听循环</span>    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">getReaders</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self)</span>:</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> [self._selectables[fd] <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> fd <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> self._reads]    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">getWriters</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self)</span>:</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> [self._selectables[fd] <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> fd <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> self._writes]</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li></ul>

implementer表示PollReactor实现了IReactorFDSet的接口的方法: 
/twisted/internet/interfaces.py

_doReadOrWrite方法的实现在pollreactor的基类_pollLikeMixin中:

<code class="hljs python has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># twisted/internet/posixbase.py</span><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">_PollLikeMixin</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(object)</span>:</span>    <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"""    Mixin for poll-like reactors.    Subclasses must define the following attributes::      - _POLL_DISCONNECTED - Bitmask for events indicating a connection was        lost.      - _POLL_IN - Bitmask for events indicating there is input to read.      - _POLL_OUT - Bitmask for events indicating output can be written.    Must be mixed in to a subclass of PosixReactorBase (for    _disconnectSelectable).    """</span>    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">_doReadOrWrite</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, selectable, fd, event)</span>:</span>        <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"""       文件描述符要可读,可写,能够完成工作并且能在必要时抛出异常        """</span>        why = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">None</span>        inRead = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">False</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> event & self._POLL_DISCONNECTED <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span> (event & self._POLL_IN):            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 处理断开的连接,只有当我们已经完成处理所有未决的输入时</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> fd <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> self._reads:                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 表明不会再有读事件,即读取数据已经完毕,</span>                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 并且有可能传输的另一边已经断开连接</span>                inRead = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">True</span>                why = CONNECTION_DONE            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>:                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 如果我们没有从这个描述符中读取数据,</span>                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 那么只有可能是一个错误的关闭</span>                why = CONNECTION_LOST        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>:            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>:                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> selectable.fileno() == -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>:                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 表明这个socket已经被关闭</span>                    why = _NO_FILEDESC                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>:                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> event & self._POLL_IN:                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 处理读事件</span>                        why = selectable.doRead()                        inRead = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">True</span>                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span> why <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> event & self._POLL_OUT:                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 处理写事件,读事件的eventmask是1,写事</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 件的eventmask是4,二者叠加是5,5的</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 话一般指连接关闭(这个只是我的个人理解,</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 我在做实验的时候发现连接关闭时响应事件</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 的eventmask为5),所以这里要检测只有</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 写事件出现,没有读事件出现</span>                        why = selectable.doWrite()                        inRead = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">False</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">except</span>:                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># Any exception from application code gets logged and will</span>                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># cause us to disconnect the selectable.</span>                why = sys.exc_info()[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]                log.err()        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> why:            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 处理关闭的连接</span>            self._disconnectSelectable(selectable, why, inRead)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li></ul>

_doReadOrWrite方法将根据各个socket发生的事件来调用响应的doRead,doWrite方法,或者关闭连接和报错

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">port = reactor<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.listenTCP</span>(options<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.port</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">or</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, factory,                             interface=options<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.iface</span>)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

这里reactor监听了一个端口,这个方法在reactor的基类PosixReactorBase中实现:

<code class="hljs python has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># /twisted/internet/posixbase.py</span><span class="hljs-decorator" style="color: rgb(0, 102, 102); box-sizing: border-box;">@implementer(IReactorTCP, IReactorUDP, IReactorMulticast)</span><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">PosixReactorBase</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(_SignalReactorMixin, _DisconnectSelectableMixin,ReactorBase)</span>:</span>    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">listenTCP</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, port, factory, backlog=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">50</span>, interface=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">''</span>)</span>:</span>        p = tcp.Port(port, factory, backlog, interface, self)        p.startListening()        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> p<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># /twisted/internet/tcp.py</span><span class="hljs-decorator" style="color: rgb(0, 102, 102); box-sizing: border-box;">@implementer(interfaces.IListeningPort)</span><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Port</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(base.BasePort, _SocketCloser)</span>:</span>    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">__init__</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, port, factory, backlog=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">50</span>, interface=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">''</span>, reactor=None)</span>:</span>        <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"""Initialize with a numeric port to listen on.        """</span>        base.BasePort.__init__(self, reactor=reactor)        self.port = port        self.factory = factory        self.backlog = backlog        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> abstract.isIPv6Address(interface):            self.addressFamily = socket.AF_INET6            self._addressType = address.IPv6Address        self.interface = interface    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">startListening</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self)</span>:</span>        <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"""创建和绑定socket,然后启动侦听"""</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 看看可否复用之前创建的socket</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> self._preexistingSocket <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">None</span>:            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>:                skt = self.createInternetSocket()                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> self.addressFamily == socket.AF_INET6:                    addr = _resolveIPv6(self.interface, self.port)                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>:                    addr = (self.interface, self.port)                skt.bind(addr)            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">except</span> socket.error <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> le:                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">raise</span> CannotListenError(self.interface, self.port, le)            skt.listen(self.backlog)        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>:            skt = self._preexistingSocket            self._preexistingSocket = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">None</span>            self._shouldShutdown = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">False</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># Make sure that if we listened on port 0, we update that to</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># reflect what the OS actually assigned us.</span>        self._realPortNumber = skt.getsockname()[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]        log.msg(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%s starting on %s"</span> % (                self._getLogPrefix(self.factory), self._realPortNumber))        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># The order of the next 5 lines is kind of bizarre.  If no one</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># can explain it, perhaps we should re-arrange them.</span>        self.factory.doStart() <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 启动工厂</span>        self.connected = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">True</span>        self.socket = skt        self.fileno = self.socket.fileno        self.numberAccepts = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>        self.<span class="KSFIND_CLASS_SELECT" id="0KSFindDIV" style="text-align: center; -webkit-box-shadow: rgba(0, 0, 0, 0.74902) 0px 1px 3px; border: 0px solid rgb(239, 210, 0); visibility: visible !important; bottom: 0px !important; left: 0px !important; right: 0px !important; top: 0px !important; height: inherit !important; width: inherit !important; float: none !important; color: black !important; display: inline !important; padding-bottom: 1px !important; padding-top: 2px !important; position: relative !important; z-index: 3000050 !important; border-radius: 3px !important; box-sizing: border-box; background: none 0px 0px repeat scroll rgb(239, 210, 0) !important;">startReading</span>()         <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 将该对象添加到reactor的polling对象的跟踪列表中</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li></ul>

在这里,listenTCP创建一个监听某个端口的socket,并且将其添加到reactor的polling对象的跟踪列表中,一旦有客户端访问该服务器,这个reactor就会监控到,并且处理它。listenTCP返回一个Port对象,当客户端有连接请求时,便会调用doRead方法:

<code class="hljs python has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># twisted/internet/tcp.py</span><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">doRead</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self)</span>:</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>:            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> platformType == <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"posix"</span>:                numAccepts = self.numberAccepts            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>:                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># win32下只能调用一次socket.accept方法</span>                numAccepts = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> i <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> range(numAccepts):                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> self.disconnecting:                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>:                    skt, addr = self.socket.accept()                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 获得客户端连接的socket</span>                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">except</span> socket.error <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> e:                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> e.args[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> (EWOULDBLOCK, EAGAIN):                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># EWOULDBLOCK 操作阻塞</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># EAGAIN 再次尝试</span>                        self.numberAccepts = i                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">elif</span> e.args[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] == EPERM:                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 操作不允许</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># Netfilter on Linux may have rejected the</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># connection, but we get told to try to accept()</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># anyway.</span>                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">continue</span>                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">elif</span> e.args[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> (EMFILE, ENOBUFS, ENFILE, ENOMEM, ECONNABORTED):                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># EMFILE 过多的文件描述符</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># ENOBUFS 缓存区不足</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># ENFILE 文件表溢出</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># Linux gives EMFILE when a process is not allowed</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># to allocate any more file descriptors.  *BSD and</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># Win32 give (WSA)ENOBUFS.  Linux can also give</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># ENFILE if the system is out of inodes, or ENOMEM</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># if there is insufficient memory to allocate a new</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># dentry.  ECONNABORTED is documented as possible on</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># both Linux and Windows, but it is not clear</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># whether there are actually any circumstances under</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># which it can happen (one might expect it to be</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># possible if a client sends a FIN or RST after the</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># server sends a SYN|ACK but before application code</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># calls accept(2), however at least on Linux this</span>                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># _seems_ to be short-circuited by syncookies.</span>                        log.msg(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Could not accept new connection (%s)"</span> % (                            errorcode[e.args[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]],))                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">raise</span>                fdesc._setCloseOnExec(skt.fileno())                protocol = self.factory.buildProtocol(self._buildAddr(addr))                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> protocol <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">None</span>:                    skt.close()                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">continue</span>                s = self.sessionno                self.sessionno = s+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>                transport = self.transport(skt, protocol, addr, self, s, self.reactor)                protocol.makeConnection(transport)            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>:                self.numberAccepts = self.numberAccepts+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">except</span>:            log.deferr()</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li></ul>

在doRead方法中,调用accept产生了用于接收客户端数据的套接字,将套接字与transport绑定,然后创建Protocol对象,然后把transport加入到reactor的读集合。

<code class="hljs ruby has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">protocol = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>.factory.buildProtocol(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>._buildAddr(addr))transport = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>.transport(skt, protocol, addr, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>, s, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>.reactor)protocol.makeConnection(transport)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

factory对象(Factory以后再讲)调用buildProtocol方法创建了我们自定义的Protocol类对象,然后创建transport之后调用了protocol的makeConnection方法,改方法的实现在其父类BaseProtocol中:

<code class="hljs python has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># /twisted/internet/protocol.py</span><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">BaseProtocol</span>:</span>    connected = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>    transport = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">None</span>    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">makeConnection</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, transport)</span>:</span>        self.connected = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>        self.transport = transport        self.connectionMade()    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">connectionMade</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self)</span>:</span>        <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"""Called when a connection is made.        This may be considered the initializer of the protocol, because        it is called when the connection is completed.  For clients,        this is called once the connection to the server has been        established; for servers, this is called after an accept() call        stops blocking and a socket has been received.  If you need to        send any greeting or initial message, do it here.        """</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>

在这里它调用了我们自定义的makeConnection方法,这样服务器端和客户端就可以进行数据传输了

当客户端有数据到来时,就会调用transport的doRead方法进行数据读取了。而Connection是transport实例的类的父类,它实现了doRead方法:

<code class="hljs python has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># /twisted/internet/tcp.py</span><span class="hljs-decorator" style="color: rgb(0, 102, 102); box-sizing: border-box;">@implementer(interfaces.ITCPTransport, interfaces.ISystemHandle)</span><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Connection</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(_TLSConnectionMixin, abstract.FileDescriptor, _SocketCloser,                 _AbortingMixin)</span>:</span>     <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">doRead</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self)</span>:</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>:            data = self.socket.recv(self.bufferSize)        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">except</span> socket.error <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> se:            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> se.args[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] == EWOULDBLOCK:                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 如果被阻塞直接返回</span>                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>:                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 断开连接</span>                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> main.CONNECTION_LOST        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> self._dataReceived(data)    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">_dataReceived</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, data)</span>:</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span> data:            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> main.CONNECTION_DONE        rval = self.protocol.dataReceived(data)        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> rval <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">None</span>:            offender = self.protocol.dataReceived            warningFormat = (                <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'Returning a value other than None from %(fqpn)s is '</span>                <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'deprecated since %(version)s.'</span>)            warningString = deprecate.getDeprecationWarningString(                offender, versions.Version(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'Twisted'</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">11</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>),                format=warningFormat)            deprecate.warnAboutFunction(offender, warningString)        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> rval</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li></ul>

_dataReceived方法将调用我们重写的protocol的dataReceived方法处理数据 
reactor.run()方法的是reactor的基类_SignalReactorMixin实现的:

<code class="hljs python has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">_SignalReactorMixin</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(object)</span>:</span>    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">startRunning</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, installSignalHandlers=True)</span>:</span>        self._installSignalHandlers = installSignalHandlers        ReactorBase.startRunning(self)    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">run</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self, installSignalHandlers=True)</span>:</span>    self.startRunning(installSignalHandlers=installSignalHandlers)        self.mainLoop()    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">mainLoop</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(self)</span>:</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> self._started:            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>:                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> self._started:                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># Advance simulation time in delayed event</span>                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># processors.</span>                    self.runUntilCurrent()                    t2 = self.timeout()                    t = self.running <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> t2                    self.doIteration(t)            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">except</span>:                log.msg(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Unexpected error in main loop."</span>)                log.err()            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>:                log.msg(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'Main loop terminated.'</span>)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li></ul><div class="save_code tracking-ad" data-mod="popu_249" style="box-sizing: border-box; position: absolute; height: 60px; right: 30px; top: 5px; color: rgb(255, 255, 255); cursor: pointer; z-index: 2;"><a target=_blank target="_blank" style="color: rgb(202, 0, 0); box-sizing: border-box;"><img src="http://static.blog.csdn.net/images/save_snippets.png" style="border: none; box-sizing: border-box; max-width: 100%;" alt="" /></a></div>

pollreactor的基类PosixReactorBase有两个基类,分别是_SignalReactorMixin和ReactorBase,由于_SignalReactorMixin和ReactorBase都实现了startRunning方法,所以根据继承的mro顺序的话,会先调用_SignalReactorMixin的,这样的话需要在最后再调用ReactorBase的startRunning方法

在这里mainloop将启动主循环了,mainloop调用上面讲的doIterarion方法来监控一组描述符,一旦有事件准备好读写,就调用事件处理程序来处理。

以上就是对于这个简单例子的简要分析,从创建事件监听循环,到与客户端建立连接。有一些细节我并没有做出说明(因为我也是边阅读源码边写博客),如果有兴趣可以仔细阅读源码,本文难免存在疏漏和错误,欢迎读者给与指正。因为要考研,我的时间并不是很多,但我至少每个月会写一篇这样的文章


参考: 
1.http://www.jianshu.com/p/26ae331b09b0 
2.https://docs.python.org/2/library/errno.html?highlight=errno#module-errno 
3.https://github.com/twisted/twisted/tree/trunk/twisted 
4.https://docs.python.org/2/library/select.html?highlight=select#module-select

0
0 0
原创粉丝点击