mirror of
https://github.com/fofolee/uTools-Manuals.git
synced 2025-06-08 23:14:06 +08:00
39 lines
28 KiB
HTML
39 lines
28 KiB
HTML
<div class="body" role="main"><div class="section" id="module-selectors"><h1><span class="yiyi-st" id="yiyi-10">18.4.<a class="reference internal" href="#module-selectors" title="selectors: High-level I/O multiplexing."><code class="xref py py-mod docutils literal"><span class="pre">selectors</span></code></a> — 高层 I/O 多路复用 </span></h1><div class="versionadded"><p><span class="yiyi-st" id="yiyi-11"><span class="versionmodified">3.4 版新加入。</span></span></p></div><p><span class="yiyi-st" id="yiyi-12"><strong>源码︰</strong><a class="reference external" href="https://hg.python.org/cpython/file/3.5/Lib/selectors.py">Lib/selectors.py</a></span></p><div class="section" id="introduction"><h2><span class="yiyi-st" id="yiyi-13">18.4.1. </span><span class="yiyi-st" id="yiyi-14">介绍 </span></h2><p><span class="yiyi-st" id="yiyi-15">这个模块允许高层高效的 I/O 多路复用,建立在 <a class="reference internal" href="select.html#module-select" title="select: Wait for I/O completion on multiple streams."><code class="xref py py-mod docutils literal"><span class="pre">选择</span></code></a> 模块原函数基础之上。</span><span class="yiyi-st" id="yiyi-16">鼓励用户使用此模块,除非他们想精确控制系统级别原函数的使用。</span></p><p><span class="yiyi-st" id="yiyi-17">它定义了 <a class="reference internal" href="#selectors.BaseSelector" title="selectors.BaseSelector"><code class="xref py py-class docutils literal"><span class="pre">BaseSelectorr</span></code></a> 抽象基类,以及几种具体的实现 (<a class="reference internal" href="#selectors.KqueueSelector" title="selectors.KqueueSelector"><code class="xref py py-class docutils literal"><span class="pre"> KqueueSelectorr</span></code></a>, <a class="reference internal" href="#selectors.EpollSelector" title="selectors.EpollSelector"><code class="xref py py-class docutils literal"><span class="pre">EpollSelectorr</span></code></a>...),可用多个文件对象上等待 I/O 准备就绪的通知。</span><span class="yiyi-st" id="yiyi-18">在下文中,"文件对象"指任何有 <code class="xref py py-meth docutils literal"><span class="pre">fileno()</span></code> 方法或原始文件描述符的对象。</span><span class="yiyi-st" id="yiyi-19">请参阅 <a class="reference internal" href="../glossary.html#term-file-object"><span class="xref std std-term">文件对象</span></a>。</span></p><p><span class="yiyi-st" id="yiyi-20"><a class="reference internal" href="#selectors.DefaultSelector" title="selectors.DefaultSelector"><code class="xref py py-class docutils literal"><span class="pre">DefaultSelector</span></code></a> 是当前平台上可用的最有效实现的别名︰ 这应该是大多数用户的默认选择。</span></p><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-21">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-22">支持的文件对象的类型取决于平台︰ 在 Windows 上,支持套接字,但不支持管道,而在 Unix 上,两者都受支持 (某些其他类型可能也支持,比如 fifo 或特殊文件设备)。</span></p></div><div class="admonition seealso"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-23">令请参阅</span></p><dl class="last docutils"><dt><span class="yiyi-st" id="yiyi-24"><a class="reference internal" href="select.html#module-select" title="select: Wait for I/O completion on multiple streams."><code class="xref py py-mod docutils literal"><span class="pre">select</span></code></a></span></dt><dd><span class="yiyi-st" id="yiyi-25">低层 I/O 多路复用模块。</span></dd></dl></div></div><div class="section" id="classes"><h2><span class="yiyi-st" id="yiyi-26">18.4.2. </span><span class="yiyi-st" id="yiyi-27">类 </span></h2><p><span class="yiyi-st" id="yiyi-28">类层次结构︰</span></p><pre><code class="language-python"><span></span><span class="n">BaseSelector</span>
|
||
<span class="o">+--</span> <span class="n">SelectSelector</span>
|
||
<span class="o">+--</span> <span class="n">PollSelector</span>
|
||
<span class="o">+--</span> <span class="n">EpollSelector</span>
|
||
<span class="o">+--</span> <span class="n">DevpollSelector</span>
|
||
<span class="o">+--</span> <span class="n">KqueueSelector</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-29">在下文中,<em>事件</em> 是指那些等待I/O 事件的给定的文件对象的位掩码。</span><span class="yiyi-st" id="yiyi-30">它可以是下面的模块常量的组合︰</span></p><span class="yiyi-st" id="yiyi-108"> <blockquote> <div><table border="1" class="docutils"> <colgroup> <col width="33%"/> <col width="67%"/> </colgroup> <thead valign="bottom"> <tr class="row-odd"><th class="head">Constant</th> <th class="head">Meaning</th> </tr> </thead> <tbody valign="top"> <tr class="row-even"><td><code class="xref py py-const docutils literal"><span class="pre">EVENT_READ</span></code></td> <td>Available for read</td> </tr> <tr class="row-odd"><td><code class="xref py py-const docutils literal"><span class="pre">EVENT_WRITE</span></code></td> <td>Available for write</td> </tr> </tbody> </table> </div></blockquote></span><dl class="class"><dt id="selectors.SelectorKey"><span class="yiyi-st" id="yiyi-31"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">SelectorKey</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-32"><a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 是一个用来将文件对象关联到其底层文件描述符,选定的事件掩码和附加的数据的 <a class="reference internal" href="collections.html#collections.namedtuple" title="collections.namedtuple"><code class="xref py py-class docutils literal"><span class="pre">namedtuple</span></code></a>。</span><span class="yiyi-st" id="yiyi-33">它由 <a class="reference internal" href="#selectors.BaseSelector" title="selectors.BaseSelector"><code class="xref py py-class docutils literal"><span class="pre">BaseSelector</span></code></a> 的几种方法返回。</span></p><dl class="attribute"><dt id="selectors.SelectorKey.fileobj"><span class="yiyi-st" id="yiyi-34"> <code class="descname">fileobj</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-35">注册的文件对象。</span></p></dd></dl><dl class="attribute"><dt id="selectors.SelectorKey.fd"><span class="yiyi-st" id="yiyi-36"> <code class="descname">fd</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-37">底层的文件描述符。</span></p></dd></dl><dl class="attribute"><dt id="selectors.SelectorKey.events"><span class="yiyi-st" id="yiyi-38"> <code class="descname">events</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-39">该文件对象必须等待的事件。</span></p></dd></dl><dl class="attribute"><dt id="selectors.SelectorKey.data"><span class="yiyi-st" id="yiyi-40"> <code class="descname">data</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-41">可选的与此文件对象相关联的不透明数据︰ 例如,这可以用来存储每个客户端的会话 id。</span></p></dd></dl></dd></dl><dl class="class"><dt id="selectors.BaseSelector"><span class="yiyi-st" id="yiyi-42"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">BaseSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-43"><a class="reference internal" href="#selectors.BaseSelector" title="selectors.BaseSelector"><code class="xref py py-class docutils literal"><span class="pre">BaseSelector</span></code></a> 用来等待多个文件对象的I/O 事件的准备。</span><span class="yiyi-st" id="yiyi-44">它支持文件流注册、 注销和带可选超时值的等待这些流的 I/O 事件的方法。</span><span class="yiyi-st" id="yiyi-45">它是一个抽象的基类,因此不能实例化。</span><span class="yiyi-st" id="yiyi-46">使用 <a class="reference internal" href="#selectors.DefaultSelector" title="selectors.DefaultSelector"><code class="xref py py-class docutils literal"><span class="pre">DefaultSelector</span></code></a>来替代 或者用 <a class="reference internal" href="#selectors.SelectSelector" title="selectors.SelectSelector"><code class="xref py py-class docutils literal"><span class="pre">SelectSelector</span></code></a>,<a class="reference internal" href="#selectors.KqueueSelector" title="selectors.KqueueSelector"><code class="xref py py-class docutils literal"><span class="pre">KqueueSelector</span></code></a> 等。</span><span class="yiyi-st" id="yiyi-47">如果您想要明确使用一种实现,和您的平台支持它。</span><span class="yiyi-st" id="yiyi-48"><a class="reference internal" href="#selectors.BaseSelector" title="selectors.BaseSelector"><code class="xref py py-class docutils literal"><span class="pre">BaseSelector</span></code></a> 和其具体的实现支持 <a class="reference internal" href="../glossary.html#term-context-manager"><span class="xref std std-term">上下文管理器</span></a> 协议。</span></p><dl class="method"><dt id="selectors.BaseSelector.register"><span class="yiyi-st" id="yiyi-49"> <em class="property">abstractmethod </em><code class="descname">register</code><span class="sig-paren">(</span><em>fileobj</em>, <em>events</em>, <em>data=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-50">注册一个文件对象到选择器来监视它的 I/O 事件。</span></p><p><span class="yiyi-st" id="yiyi-51"><em>fileobj</em> 是要监视的文件对象。</span><span class="yiyi-st" id="yiyi-52">它可能是一个整型文件描述符或有 <code class="docutils literal"><span class="pre">fileno()</span></code> 方法的对象。</span><span class="yiyi-st" id="yiyi-53"><em>events</em> 是要监视的事件的位掩码。</span><span class="yiyi-st" id="yiyi-54"><em>data</em> 是不透明的对象。</span></p><p><span class="yiyi-st" id="yiyi-55">这返回一个新的 <a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 实例,或者因无效的事件掩码或文件描述符抛出 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal"><span class="pre">ValueError</span></code></a> 错误,或者如果文件对象已注册则抛出 <a class="reference internal" href="exceptions.html#KeyError" title="KeyError"><code class="xref py py-exc docutils literal"><span class="pre">KeyError</span></code></a> 错误。</span></p></dd></dl><dl class="method"><dt id="selectors.BaseSelector.unregister"><span class="yiyi-st" id="yiyi-56"> <em class="property">abstractmethod </em><code class="descname">unregister</code><span class="sig-paren">(</span><em>fileobj</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-57">从选择器注销一个文件对象并移除对它的监视。</span><span class="yiyi-st" id="yiyi-58">文件对象被注销前应先关闭。</span></p><p><span class="yiyi-st" id="yiyi-59"><em>fileobj</em> 必须是先前注册过的文件对象。</span></p><p><span class="yiyi-st" id="yiyi-60">这返回关联的 <a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 实例,或者如果 <em>fileobj</em>未注册则抛出 <a class="reference internal" href="exceptions.html#KeyError" title="KeyError"><code class="xref py py-exc docutils literal"><span class="pre">KeyError</span></code></a>错误。</span><span class="yiyi-st" id="yiyi-61">如果 <em>fileobj</em> 无效则抛出<a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal"><span class="pre">ValueError</span></code></a>错误(例如,</span><span class="yiyi-st" id="yiyi-62">它没有 <code class="docutils literal"><span class="pre">fileno()</span></code> 方法或其 <code class="docutils literal"><span class="pre">fileno()</span></code> 方法有无效的返回值)。</span></p></dd></dl><dl class="method"><dt id="selectors.BaseSelector.modify"><span class="yiyi-st" id="yiyi-63"> <code class="descname">modify</code><span class="sig-paren">(</span><em>fileobj</em>, <em>events</em>, <em>data=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-64">更改已注册的文件对象的监视事件或附加数据。</span></p><p><span class="yiyi-st" id="yiyi-65">这就相当于先 <code class="xref py py-meth docutils literal"><span class="pre">BaseSelector.unregister(fileobj)()</span></code> 再 <code class="xref py py-meth docutils literal"><span class="pre">BaseSelector.register (fileobj,</span> <span class="pre">events,</span> <span class="pre">data)()</span></code>,只是,它可以更有效地执行。</span></p><p><span class="yiyi-st" id="yiyi-66">这返回一个新的 <a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 实例,或者因无效的事件掩码或文件描述符抛出 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal"><span class="pre">ValueError</span></code></a> 错误,或者如果文件对象已注册则抛出 <a class="reference internal" href="exceptions.html#KeyError" title="KeyError"><code class="xref py py-exc docutils literal"><span class="pre">KeyError</span></code></a> 错误。</span></p></dd></dl><dl class="method"><dt id="selectors.BaseSelector.select"><span class="yiyi-st" id="yiyi-67"> <em class="property">abstractmethod </em><code class="descname">select</code><span class="sig-paren">(</span><em>timeout=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-68">等到一些已注册的文件对象准备好或者超时。</span></p><p><span class="yiyi-st" id="yiyi-69">如果 <code class="docutils literal"><span class="pre">timeout</span> <span class="pre">></span> <span class="pre">0</span></code>,会指定最长的等待时间,以秒为单位。</span><span class="yiyi-st" id="yiyi-70">如果 <code class="docutils literal"><span class="pre">timeout</span> <span class="pre">< =</span> <span class="pre">0</span></code>,调用不会阻塞并会报告目前准备好的文件对象。</span><span class="yiyi-st" id="yiyi-71">如果 <em>timeout</em> 是 <code class="docutils literal"><span class="pre">None</span></code>,调用将会阻塞直到一个监视的文件对象准备好。</span></p><p><span class="yiyi-st" id="yiyi-72">这将返回一个以 <code class="docutils literal"><span class="pre">(key,</span> <span class="pre">events)</span></code> 元组为元素的列表,每一个元祖代表一个准备好的文件对象。</span></p><p><span class="yiyi-st" id="yiyi-73"><em>key</em> 是对应于一个准备好的文件对象的<a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 实例。</span><span class="yiyi-st" id="yiyi-74"><em>events</em> 是该文件对象上准备好的事件位掩码。</span></p><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-75">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-76">如果当前进程接收到信号,此方法可以在超时前或任何文件对象准备好前返回:在这种情况下,将返回一个空列表。</span></p></div><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-77"><span class="versionmodified">3.5 版本中的更改︰</span>当被一个信号中断时,如果信号处理程序不抛出异常 (见 <span class="target" id="index-0"></span> <a class="pep reference external" href="https://www.python.org/dev/peps/pep-0475"><strong>PEP 475</strong></a> 原因),现在选择器再次重新计算超时,而不是在超时前返回一个空的事件列表。</span></p></div></dd></dl><dl class="method"><dt id="selectors.BaseSelector.close"><span class="yiyi-st" id="yiyi-78"> <code class="descname">close</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-79">关闭选择器。</span></p><p><span class="yiyi-st" id="yiyi-80">这个必须调用以确保所有底层资源被释放。</span><span class="yiyi-st" id="yiyi-81">一旦选择器被关闭就不能再使用。</span></p></dd></dl><dl class="method"><dt id="selectors.BaseSelector.get_key"><span class="yiyi-st" id="yiyi-82"> <code class="descname">get_key</code><span class="sig-paren">(</span><em>fileobj</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-83">返回一个与已注册的文件对象关联的键值。</span></p><p><span class="yiyi-st" id="yiyi-84">这返回关联此文件对象的 <a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 实例,或如果文件对象未注册则抛出 <a class="reference internal" href="exceptions.html#KeyError" title="KeyError"><code class="xref py py-exc docutils literal"><span class="pre">KeyError</span></code></a>错误。</span></p></dd></dl><dl class="method"><dt id="selectors.BaseSelector.get_map"><span class="yiyi-st" id="yiyi-85"> <em class="property">abstractmethod </em><code class="descname">get_map</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-86">返回文件对象到选择器键值的映射。</span></p><p><span class="yiyi-st" id="yiyi-87">这将返回一个已注册的文件对象到与其关联的 <a class="reference internal" href="#selectors.SelectorKey" title="selectors.SelectorKey"><code class="xref py py-class docutils literal"><span class="pre">SelectorKey</span></code></a> 实例的映射的 <a class="reference internal" href="collections.abc.html#collections.abc.Mapping" title="collections.abc.Mapping"><code class="xref py py-class docutils literal"><span class="pre">Mapping</span></code></a> 实例。</span></p></dd></dl></dd></dl><dl class="class"><dt id="selectors.DefaultSelector"><span class="yiyi-st" id="yiyi-88"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">DefaultSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-89">默认选择器类使用在当前平台上可用的最有效的实现。</span><span class="yiyi-st" id="yiyi-90">这应该是大多数用户的默认选择。</span></p></dd></dl><dl class="class"><dt id="selectors.SelectSelector"><span class="yiyi-st" id="yiyi-91"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">SelectSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-92">基于<a class="reference internal" href="select.html#select.select" title="select.select"><code class="xref py py-func docutils literal"><span class="pre">select.select()</span></code></a>的选择器。</span></p></dd></dl><dl class="class"><dt id="selectors.PollSelector"><span class="yiyi-st" id="yiyi-93"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">PollSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-94">基于<a class="reference internal" href="select.html#select.poll" title="select.poll"><code class="xref py py-func docutils literal"><span class="pre">select.poll()</span></code></a>的选择器。</span></p></dd></dl><dl class="class"><dt id="selectors.EpollSelector"><span class="yiyi-st" id="yiyi-95"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">EpollSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-96">基于<a class="reference internal" href="select.html#select.epoll" title="select.epoll"><code class="xref py py-func docutils literal"><span class="pre">select.epoll()</span></code></a>的选择器。</span></p><dl class="method"><dt id="selectors.EpollSelector.fileno"><span class="yiyi-st" id="yiyi-97"> <code class="descname">fileno</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-98">这将返回底层的 <a class="reference internal" href="select.html#select.epoll" title="select.epoll"><code class="xref py py-func docutils literal"><span class="pre">select.epoll()</span></code></a> 对象所使用的文件描述符。</span></p></dd></dl></dd></dl><dl class="class"><dt id="selectors.DevpollSelector"><span class="yiyi-st" id="yiyi-99"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">DevpollSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-100">基于<a class="reference internal" href="select.html#select.devpoll" title="select.devpoll"><code class="xref py py-func docutils literal"><span class="pre">select.devpoll()</span></code></a>的选择器。</span></p><dl class="method"><dt id="selectors.DevpollSelector.fileno"><span class="yiyi-st" id="yiyi-101"> <code class="descname">fileno</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-102">这将返回底层的 <a class="reference internal" href="select.html#select.devpoll" title="select.devpoll"><code class="xref py py-func docutils literal"><span class="pre">select.devpoll()</span></code></a> 对象所使用的文件描述符。</span></p></dd></dl><div class="versionadded"><p><span class="yiyi-st" id="yiyi-103"><span class="versionmodified">3.5版本中新加入。</span></span></p></div></dd></dl><dl class="class"><dt id="selectors.KqueueSelector"><span class="yiyi-st" id="yiyi-104"> <em class="property">class </em><code class="descclassname">selectors.</code><code class="descname">KqueueSelector</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-105">基于<a class="reference internal" href="select.html#select.kqueue" title="select.kqueue"><code class="xref py py-func docutils literal"><span class="pre">select.kqueue()</span></code></a>的选择器。</span></p><dl class="method"><dt id="selectors.KqueueSelector.fileno"><span class="yiyi-st" id="yiyi-106"> <code class="descname">fileno</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-107">这将返回底层的 <a class="reference internal" href="select.html#select.kqueue" title="select.kqueue"><code class="xref py py-func docutils literal"><span class="pre">select.kqueue()</span></code></a> 对象所使用的文件描述符。</span></p></dd></dl></dd></dl></div><div class="section" id="examples"><h2><span class="yiyi-st" id="yiyi-109">18.4.3. </span><span class="yiyi-st" id="yiyi-110">示例 </span></h2><p><span class="yiyi-st" id="yiyi-111">这里是一个简单的回显服务器的实现︰</span></p><pre><code class="language-python"><span></span><span class="kn">import</span> <span class="nn">selectors</span>
|
||
<span class="kn">import</span> <span class="nn">socket</span>
|
||
|
||
<span class="n">sel</span> <span class="o">=</span> <span class="n">selectors</span><span class="o">.</span><span class="n">DefaultSelector</span><span class="p">()</span>
|
||
|
||
<span class="k">def</span> <span class="nf">accept</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">mask</span><span class="p">):</span>
|
||
<span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span> <span class="c1"># Should be ready</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'accepted'</span><span class="p">,</span> <span class="n">conn</span><span class="p">,</span> <span class="s1">'from'</span><span class="p">,</span> <span class="n">addr</span><span class="p">)</span>
|
||
<span class="n">conn</span><span class="o">.</span><span class="n">setblocking</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="n">sel</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="n">selectors</span><span class="o">.</span><span class="n">EVENT_READ</span><span class="p">,</span> <span class="n">read</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">read</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="n">mask</span><span class="p">):</span>
|
||
<span class="n">data</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span> <span class="c1"># Should be ready</span>
|
||
<span class="k">if</span> <span class="n">data</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'echoing'</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="s1">'to'</span><span class="p">,</span> <span class="n">conn</span><span class="p">)</span>
|
||
<span class="n">conn</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="c1"># Hope it won't block</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s1">'closing'</span><span class="p">,</span> <span class="n">conn</span><span class="p">)</span>
|
||
<span class="n">sel</span><span class="o">.</span><span class="n">unregister</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
|
||
<span class="n">conn</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||
|
||
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">()</span>
|
||
<span class="n">sock</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="s1">'localhost'</span><span class="p">,</span> <span class="mi">1234</span><span class="p">))</span>
|
||
<span class="n">sock</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span>
|
||
<span class="n">sock</span><span class="o">.</span><span class="n">setblocking</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
|
||
<span class="n">sel</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">selectors</span><span class="o">.</span><span class="n">EVENT_READ</span><span class="p">,</span> <span class="n">accept</span><span class="p">)</span>
|
||
|
||
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
||
<span class="n">events</span> <span class="o">=</span> <span class="n">sel</span><span class="o">.</span><span class="n">select</span><span class="p">()</span>
|
||
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">mask</span> <span class="ow">in</span> <span class="n">events</span><span class="p">:</span>
|
||
<span class="n">callback</span> <span class="o">=</span> <span class="n">key</span><span class="o">.</span><span class="n">data</span>
|
||
<span class="n">callback</span><span class="p">(</span><span class="n">key</span><span class="o">.</span><span class="n">fileobj</span><span class="p">,</span> <span class="n">mask</span><span class="p">)</span>
|
||
</code></pre></div></div></div> |