uTools-Manuals/docs/python/asyncore.html
2019-04-21 11:50:48 +08:00

58 lines
34 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<div class="body" role="main"><div class="section" id="module-asyncore"><h1><span class="yiyi-st" id="yiyi-10">18.6. <a class="reference internal" href="#module-asyncore" title="asyncore: A base class for developing asynchronous socket handling services."><code class="xref py py-mod docutils literal"><span class="pre">asyncore</span></code></a> — 异步套接字处理</span></h1><p><span class="yiyi-st" id="yiyi-11"><strong>源代码:</strong> <a class="reference external" href="https://hg.python.org/cpython/file/3.5/Lib/asyncore.py">Lib / asyncore.py</a></span></p><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-12">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-13">此模块仅用于向后兼容。</span><span class="yiyi-st" id="yiyi-14">对于新代码,我们建议使用<a class="reference internal" href="asyncio.html#module-asyncio" title="asyncio: Asynchronous I/O, event loop, coroutines and tasks."><code class="xref py py-mod docutils literal"><span class="pre">asyncio</span></code></a></span></p></div><p><span class="yiyi-st" id="yiyi-15">此模块提供用于编写​​异步套接字服务客户端和服务器的基本基础结构</span></p><p><span class="yiyi-st" id="yiyi-16">在单个处理器上有一个程序只有两种方法可以“一次处理多个事件”。多线程编程是最简单和最流行的方法,但还有另一种非常不同的技术,具有几乎所有的多线程优势,而没有实际使用多线程。</span><span class="yiyi-st" id="yiyi-17">这真的只是实用的如果你的程序大部分是I / O绑定。</span><span class="yiyi-st" id="yiyi-18">如果你的程序是处理器绑定,那么抢先调度的线程可能是你真正需要的。</span><span class="yiyi-st" id="yiyi-19">然而,网络服务器很少受处理器限制。</span></p><p><span class="yiyi-st" id="yiyi-20">如果您的操作系统在其I / O库中支持<code class="xref c c-func docutils literal"><span class="pre">select()</span></code>系统调用几乎所有操作系统调用则可以使用它同时处理多个通信通道在“背景”中执行I / O时执行其他工作。虽然此策略看起来很奇怪和复杂特别是在开始时它在许多方面比多线程编程更容易理解和控制。</span><span class="yiyi-st" id="yiyi-21"><a class="reference internal" href="#module-asyncore" title="asyncore: A base class for developing asynchronous socket handling services."><code class="xref py py-mod docutils literal"><span class="pre">asyncore</span></code></a>模块解决了许多困难的问题,使构建复杂的高性能网络服务器和客户端的任务变得轻而易举。</span><span class="yiyi-st" id="yiyi-22">对于“会话”应用程序和协议,伴随的<a class="reference internal" href="asynchat.html#module-asynchat" title="asynchat: Support for asynchronous command/response protocols."><code class="xref py py-mod docutils literal"><span class="pre">asynchat</span></code></a>模块是无价的。</span></p><p><span class="yiyi-st" id="yiyi-23">两个模块的基本思想是创建一个或多个网络<em>通道</em>,类<a class="reference internal" href="#asyncore.dispatcher" title="asyncore.dispatcher"><code class="xref py py-class docutils literal"><span class="pre">asyncore.dispatcher</span></code></a><a class="reference internal" href="asynchat.html#asynchat.async_chat" title="asynchat.async_chat"><code class="xref py py-class docutils literal"><span class="pre">asynchat.async_chat</span></code></a>的实例。</span><span class="yiyi-st" id="yiyi-24">如果您没有提供自己的<em>映射</em>,则创建通道会将它们添加到由<a class="reference internal" href="#asyncore.loop" title="asyncore.loop"><code class="xref py py-func docutils literal"><span class="pre">loop()</span></code></a>函数使用的全局映射中。</span></p><p><span class="yiyi-st" id="yiyi-25">一旦创建了初始通道,调用<a class="reference internal" href="#asyncore.loop" title="asyncore.loop"><code class="xref py py-func docutils literal"><span class="pre">loop()</span></code></a>函数就会激活通道服务,直到最后一个通道(包括在异步服务期间已经添加到映射的任何通道)关闭了。</span></p><dl class="function"><dt id="asyncore.loop"><span class="yiyi-st" id="yiyi-26"> <code class="descclassname">asyncore.</code><code class="descname">loop</code><span class="sig-paren">(</span><span class="optional">[</span><em>timeout</em><span class="optional">[</span>, <em>use_poll</em><span class="optional">[</span>, <em>map</em><span class="optional">[</span>, <em>count</em><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-27">输入轮询循环,在计数过程或所有打开的通道关闭后终止循环。</span><span class="yiyi-st" id="yiyi-28">所有参数都是可选的。</span><span class="yiyi-st" id="yiyi-29"><em>count</em>参数默认为None导致只有当所有通道都关闭时循环才终止。</span><span class="yiyi-st" id="yiyi-30"><em>timeout</em>参数设置适当的<a class="reference internal" href="select.html#select.select" title="select.select"><code class="xref py py-func docutils literal"><span class="pre">select()</span></code></a><a class="reference internal" href="select.html#select.poll" title="select.poll"><code class="xref py py-func docutils literal"><span class="pre">poll()</span></code></a>调用的超时参数以秒为单位默认值为30秒。</span><span class="yiyi-st" id="yiyi-31"><em>use_poll</em>参数如果为true则表示应该优先于<a class="reference internal" href="select.html#select.select" title="select.select"><code class="xref py py-func docutils literal"><span class="pre">select()</span></code></a>使用<a class="reference internal" href="select.html#select.poll" title="select.poll"><code class="xref py py-func docutils literal"><span class="pre">poll()</span></code></a>(默认值为<code class="docutils literal"><span class="pre">False</span></code></span></p><p><span class="yiyi-st" id="yiyi-32"><em>map</em>参数是一个字典,其项目是要观看的频道。</span><span class="yiyi-st" id="yiyi-33">随着频道关闭,它们将从地图中删除。</span><span class="yiyi-st" id="yiyi-34">如果省略<em>map</em>,则使用全局映射。</span><span class="yiyi-st" id="yiyi-35">通道(<a class="reference internal" href="#asyncore.dispatcher" title="asyncore.dispatcher"><code class="xref py py-class docutils literal"><span class="pre">asyncore.dispatcher</span></code></a><a class="reference internal" href="asynchat.html#asynchat.async_chat" title="asynchat.async_chat"><code class="xref py py-class docutils literal"><span class="pre">asynchat.async_chat</span></code></a>及其子类的实例)可以在地图中自由混合。</span></p></dd></dl><dl class="class"><dt id="asyncore.dispatcher"><span class="yiyi-st" id="yiyi-36"><em class="property">class</em> <code class="descclassname">asyncore。</code> <code class="descname">分派器</code> </span></dt><dd><p><span class="yiyi-st" id="yiyi-37"><a class="reference internal" href="#asyncore.dispatcher" title="asyncore.dispatcher"><code class="xref py py-class docutils literal"><span class="pre">dispatcher</span></code></a>类是一个围绕低级套接字对象的薄包装。</span><span class="yiyi-st" id="yiyi-38">为了使它更有用,它有一些从异步循环调用的事件处理方法。</span><span class="yiyi-st" id="yiyi-39">否则,它可以被视为正常的非阻塞套接字对象。</span></p><p><span class="yiyi-st" id="yiyi-40">在某些时间或在某些连接状态中发射低级事件告诉异步循环,发生了某些更高级别的事件。</span><span class="yiyi-st" id="yiyi-41">例如,如果我们要求一个套接字连接到另一个主机,我们知道在套接字第一次可写时已经建立了连接(在这一点上,您知道您可以用成功的期望写入它) )。</span><span class="yiyi-st" id="yiyi-42">隐含的更高级别事件是:</span></p><table border="1" class="docutils"><thead valign="bottom"><tr class="row-odd"><th class="head"><span class="yiyi-st" id="yiyi-43">事件</span></th><th class="head"><span class="yiyi-st" id="yiyi-44">描述</span></th></tr></thead><tbody valign="top"><tr class="row-even"><td><span class="yiyi-st" id="yiyi-45"><code class="docutils literal"><span class="pre">handle_connect()</span></code></span></td><td><span class="yiyi-st" id="yiyi-46">由第一个读或写事件隐含</span></td></tr><tr class="row-odd"><td><span class="yiyi-st" id="yiyi-47"><code class="docutils literal"><span class="pre">handle_close()</span></code></span></td><td><span class="yiyi-st" id="yiyi-48">由没有可用数据的读取事件引起</span></td></tr><tr class="row-even"><td><span class="yiyi-st" id="yiyi-49"><code class="docutils literal"><span class="pre">handle_accepted()</span></code></span></td><td><span class="yiyi-st" id="yiyi-50">通过侦听套接字上的读取事件隐含</span></td></tr></tbody></table><p><span class="yiyi-st" id="yiyi-51">在异步处理期间,每个映射通道的<a class="reference internal" href="#asyncore.dispatcher.readable" title="asyncore.dispatcher.readable"><code class="xref py py-meth docutils literal"><span class="pre">readable()</span></code></a><a class="reference internal" href="#asyncore.dispatcher.writable" title="asyncore.dispatcher.writable"><code class="xref py py-meth docutils literal"><span class="pre">writable()</span></code></a>方法用于确定通道的套接字是否应添加到通道列表<code class="xref c c-func docutils literal"><span class="pre">select()</span></code> ed或<code class="xref c c-func docutils literal"><span class="pre">poll()</span></code> ed读取和写入事件。</span></p><p><span class="yiyi-st" id="yiyi-52">因此,该组通道事件大于基本套接字事件。</span><span class="yiyi-st" id="yiyi-53">可以在您的子类中覆盖的完整方法集如下:</span></p><dl class="method"><dt id="asyncore.dispatcher.handle_read"><span class="yiyi-st" id="yiyi-54"> <code class="descname">handle_read</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-55">当异步循环检测到通道的套接字上的<code class="xref py py-meth docutils literal"><span class="pre">read()</span></code>调用将成功时调用。</span></p></dd></dl><dl class="method"><dt id="asyncore.dispatcher.handle_write"><span class="yiyi-st" id="yiyi-56"> <code class="descname">handle_write</code><span class="sig-paren">(</span><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><span class="yiyi-st" id="yiyi-59">例如:</span></p><pre><code class="language-python"><span></span><span class="k">def</span> <span class="nf">handle_write</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">sent</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">buffer</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">buffer</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">buffer</span><span class="p">[</span><span class="n">sent</span><span class="p">:]</span>
</code></pre></dd></dl><dl class="method"><dt id="asyncore.dispatcher.handle_expt"><span class="yiyi-st" id="yiyi-60"> <code class="descname">handle_expt</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-61">当有套接字连接的带外OOB数据时调用。</span><span class="yiyi-st" id="yiyi-62">这几乎不会发生因为OOB被精心支持很少使用。</span></p></dd></dl><dl class="method"><dt id="asyncore.dispatcher.handle_connect"><span class="yiyi-st" id="yiyi-63"> <code class="descname">handle_connect</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-64">当活动开启者的套接字实际建立连接时调用。</span><span class="yiyi-st" id="yiyi-65">可能发送“欢迎”横幅,或者例如与远程端点发起协议协商。</span></p></dd></dl><dl class="method"><dt id="asyncore.dispatcher.handle_close"><span class="yiyi-st" id="yiyi-66"> <code class="descname">handle_close</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-67">在套接字关闭时调用。</span></p></dd></dl><dl class="method"><dt id="asyncore.dispatcher.handle_error"><span class="yiyi-st" id="yiyi-68"> <code class="descname">handle_error</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-69">当引发异常并且未以其他方式处理时调用。</span><span class="yiyi-st" id="yiyi-70">默认版本打印精简跟踪。</span></p></dd></dl><dl class="method"><dt id="asyncore.dispatcher.handle_accept"><span class="yiyi-st" id="yiyi-71"> <code class="descname">handle_accept</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-72">当可以与为本地端点发出<a class="reference internal" href="#asyncore.dispatcher.connect" title="asyncore.dispatcher.connect"><code class="xref py py-meth docutils literal"><span class="pre">connect()</span></code></a>调用的新远程端点建立连接时,在侦听通道(被动打开程序)上调用。</span><span class="yiyi-st" id="yiyi-73">在版本3.2中已弃用;请改用<a class="reference internal" href="#asyncore.dispatcher.handle_accepted" title="asyncore.dispatcher.handle_accepted"><code class="xref py py-meth docutils literal"><span class="pre">handle_accepted()</span></code></a></span></p><div class="deprecated"><p><span class="yiyi-st" id="yiyi-74"><span class="versionmodified">自3.2版起已弃用。</span></span></p></div></dd></dl><dl class="method"><dt id="asyncore.dispatcher.handle_accepted"><span class="yiyi-st" id="yiyi-75"> <code class="descname">handle_accepted</code><span class="sig-paren">(</span><em>sock</em>, <em>addr</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-76">当与为本地端点发出<a class="reference internal" href="#asyncore.dispatcher.connect" title="asyncore.dispatcher.connect"><code class="xref py py-meth docutils literal"><span class="pre">connect()</span></code></a>调用的新远程端点建立连接时,在侦听通道(被动打开程序)上调用。</span><span class="yiyi-st" id="yiyi-77"><em>sock</em>是可用于在连接上发送和接收数据的<em></em>套接字对象,<em>addr</em>是绑定到另一端套接字的地址的连接。</span></p><div class="versionadded"><p><span class="yiyi-st" id="yiyi-78"><span class="versionmodified">版本3.2中的新功能。</span></span></p></div></dd></dl><dl class="method"><dt id="asyncore.dispatcher.readable"><span class="yiyi-st" id="yiyi-79"> <code class="descname">readable</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-80">每次在异步循环时调用以确定是否应将通道的套接字添加到可能发生读事件的列表中。</span><span class="yiyi-st" id="yiyi-81">默认方法只返回<code class="docutils literal"><span class="pre">True</span></code>,表示默认情况下所有通道都对读事件感兴趣。</span></p></dd></dl><dl class="method"><dt id="asyncore.dispatcher.writable"><span class="yiyi-st" id="yiyi-82"> <code class="descname">writable</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-83">每次在异步循环时调用以确定是否应将通道的套接字添加到可能发生写事件的列表中。</span><span class="yiyi-st" id="yiyi-84">默认方法只返回<code class="docutils literal"><span class="pre">True</span></code>,表示默认情况下所有通道都对写事件感兴趣。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-85">此外,每个通道都委派或扩展了许多套接字方法。</span><span class="yiyi-st" id="yiyi-86">其中大多数与其套接伙伴几乎相同。</span></p><dl class="method"><dt id="asyncore.dispatcher.create_socket"><span class="yiyi-st" id="yiyi-87"> <code class="descname">create_socket</code><span class="sig-paren">(</span><em>family=socket.AF_INET</em>, <em>type=socket.SOCK_STREAM</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-88">这与创建正常的套接字相同,并且将使用相同的选项进行创建。</span><span class="yiyi-st" id="yiyi-89">有关创建套接字的信息,请参阅<a class="reference internal" href="socket.html#module-socket" title="socket: Low-level networking interface."><code class="xref py py-mod docutils literal"><span class="pre">socket</span></code></a>文档。</span></p><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-90"><span class="versionmodified">在版本3.3中更改:</span> <em>系列</em><em>类型</em>参数可以省略。</span></p></div></dd></dl><dl class="method"><dt id="asyncore.dispatcher.connect"><span class="yiyi-st" id="yiyi-91"> <code class="descname">connect</code><span class="sig-paren">(</span><em>address</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-92">与正常的套接字对象一样,<em>地址</em>是主机连接到的第一个元素的元组,第二个是端口号。</span></p></dd></dl><dl class="method"><dt id="asyncore.dispatcher.send"><span class="yiyi-st" id="yiyi-93"> <code class="descname">send</code><span class="sig-paren">(</span><em>data</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-94"><em>数据</em>发送到套接字的远程端点。</span></p></dd></dl><dl class="method"><dt id="asyncore.dispatcher.recv"><span class="yiyi-st" id="yiyi-95"> <code class="descname">recv</code><span class="sig-paren">(</span><em>buffer_size</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-96">最多从套接字的远程端点读取<em>buffer_size</em>字节。</span><span class="yiyi-st" id="yiyi-97">空字节对象意味着通道已从另一端关闭。</span></p><p><span class="yiyi-st" id="yiyi-98">请注意,即使<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><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><a class="reference internal" href="#asyncore.dispatcher.recv" title="asyncore.dispatcher.recv"><code class="xref py py-meth docutils literal"><span class="pre">recv()</span></code></a>可能引发<a class="reference internal" href="exceptions.html#BlockingIOError" title="BlockingIOError"><code class="xref py py-exc docutils literal"><span class="pre">BlockingIOError</span></code></a>已报告套接字准备好读取。</span></p></dd></dl><dl class="method"><dt id="asyncore.dispatcher.listen"><span class="yiyi-st" id="yiyi-99"> <code class="descname">listen</code><span class="sig-paren">(</span><em>backlog</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-100">监听与套接字的连接。</span><span class="yiyi-st" id="yiyi-101"><em>backlog</em>参数指定排队连接的最大数量且应至少为1最大值是系统相关的通常为5</span></p></dd></dl><dl class="method"><dt id="asyncore.dispatcher.bind"><span class="yiyi-st" id="yiyi-102"> <code class="descname">bind</code><span class="sig-paren">(</span><em>address</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-103">将套接字绑定到<em>地址</em></span><span class="yiyi-st" id="yiyi-104">套接字不必已绑定。</span><span class="yiyi-st" id="yiyi-105"><em>地址</em>的格式取决于地址系列 - 有关详细信息,请参阅<a class="reference internal" href="socket.html#module-socket" title="socket: Low-level networking interface."><code class="xref py py-mod docutils literal"><span class="pre">socket</span></code></a>文档)。</span><span class="yiyi-st" id="yiyi-106">要将套接字标记为可重用(设置<code class="xref py py-const docutils literal"><span class="pre">SO_REUSEADDR</span></code>选项),请调用<a class="reference internal" href="#asyncore.dispatcher" title="asyncore.dispatcher"><code class="xref py py-class docutils literal"><span class="pre">dispatcher</span></code></a>对象的<code class="xref py py-meth docutils literal"><span class="pre">set_reuse_addr()</span></code>方法。</span></p></dd></dl><dl class="method"><dt id="asyncore.dispatcher.accept"><span class="yiyi-st" id="yiyi-107"> <code class="descname">accept</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-108">接受连接。</span><span class="yiyi-st" id="yiyi-109">套接字必须绑定到地址并侦听连接。</span><span class="yiyi-st" id="yiyi-110">返回值可以是<code class="docutils literal"><span class="pre">None</span></code>或对<code class="docutils literal"><span class="pre">conn</span> <span class="pre">地址)</span></code>,其中<em>conn 是可用于在连接上发送和接收数据的<em></em>套接字对象,<em>address</em>是连接另一端的套接字的地址。</em></span><span class="yiyi-st" id="yiyi-111">当返回<code class="docutils literal"><span class="pre">None</span></code>时,表示连接未发生,在这种情况下,服务器应忽略此事件并继续侦听其他传入连接。</span></p></dd></dl><dl class="method"><dt id="asyncore.dispatcher.close"><span class="yiyi-st" id="yiyi-112"> <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-113">关闭套接字。</span><span class="yiyi-st" id="yiyi-114">对套接字对象的所有未来操作都将失败。</span><span class="yiyi-st" id="yiyi-115">远程端点将不再接收数据(在排队的数据被刷新之后)。</span><span class="yiyi-st" id="yiyi-116">套接字在被垃圾回收时自动关闭。</span></p></dd></dl></dd></dl><dl class="class"><dt id="asyncore.dispatcher_with_send"><span class="yiyi-st" id="yiyi-117"> <em class="property">class </em><code class="descclassname">asyncore.</code><code class="descname">dispatcher_with_send</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-118"><a class="reference internal" href="#asyncore.dispatcher" title="asyncore.dispatcher"><code class="xref py py-class docutils literal"><span class="pre">dispatcher</span></code></a>子类,它增加了简单的缓冲输出功能,对简单的客户端非常有用。</span><span class="yiyi-st" id="yiyi-119">对于更复杂的用法,请使用<a class="reference internal" href="asynchat.html#asynchat.async_chat" title="asynchat.async_chat"><code class="xref py py-class docutils literal"><span class="pre">asynchat.async_chat</span></code></a></span></p></dd></dl><dl class="class"><dt id="asyncore.file_dispatcher"><span class="yiyi-st" id="yiyi-120"> <em class="property">class </em><code class="descclassname">asyncore.</code><code class="descname">file_dispatcher</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-121">file_dispatcher接受一个文件描述器或<a class="reference internal" href="../glossary.html#term-file-object"><span class="xref std std-term">file object</span></a>以及一个可选的map参数并将其封装用于<code class="xref c c-func docutils literal"><span class="pre">poll()</span></code><code class="xref c c-func docutils literal"><span class="pre">loop()</span></code></span><span class="yiyi-st" id="yiyi-122">如果提供了文件对象或任何具有<code class="xref c c-func docutils literal"><span class="pre">fileno()</span></code>方法的方法,那么该方法将被调用并传递给<a class="reference internal" href="#asyncore.file_wrapper" title="asyncore.file_wrapper"><code class="xref py py-class docutils literal"><span class="pre">file_wrapper</span></code></a>构造函数。</span><span class="yiyi-st" id="yiyi-123">可用性UNIX。</span></p></dd></dl><dl class="class"><dt id="asyncore.file_wrapper"><span class="yiyi-st" id="yiyi-124"> <em class="property">class </em><code class="descclassname">asyncore.</code><code class="descname">file_wrapper</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-125">file_wrapper接受整数文件描述器并调用<a class="reference internal" href="os.html#os.dup" title="os.dup"><code class="xref py py-func docutils literal"><span class="pre">os.dup()</span></code></a>复制句柄以便原始句柄可以独立于file_wrapper而关闭。</span><span class="yiyi-st" id="yiyi-126">此类实现足够的方法来模拟由<a class="reference internal" href="#asyncore.file_dispatcher" title="asyncore.file_dispatcher"><code class="xref py py-class docutils literal"><span class="pre">file_dispatcher</span></code></a>类使用的套接字。</span><span class="yiyi-st" id="yiyi-127">可用性UNIX。</span></p></dd></dl><div class="section" id="asyncore-example-basic-http-client"><h2><span class="yiyi-st" id="yiyi-128">18.6.1. asyncore基本的HTTP客户端示例</span></h2><p><span class="yiyi-st" id="yiyi-129">这里是一个非常基本的HTTP客户端它使用<a class="reference internal" href="#asyncore.dispatcher" title="asyncore.dispatcher"><code class="xref py py-class docutils literal"><span class="pre">dispatcher</span></code></a>类来实现其套接字处理:</span></p><pre><code class="language-python"><span></span><span class="kn">import</span> <span class="nn">asyncore</span>
<span class="k">class</span> <span class="nc">HTTPClient</span><span class="p">(</span><span class="n">asyncore</span><span class="o">.</span><span class="n">dispatcher</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span>
<span class="n">asyncore</span><span class="o">.</span><span class="n">dispatcher</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">create_socket</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span> <span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="mi">80</span><span class="p">)</span> <span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">buffer</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">(</span><span class="s1">'GET </span><span class="si">%s</span><span class="s1"> HTTP/1.0</span><span class="se">\r\n</span><span class="s1">Host: </span><span class="si">%s</span><span class="se">\r\n\r\n</span><span class="s1">'</span> <span class="o">%</span>
<span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">host</span><span class="p">),</span> <span class="s1">'ascii'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">handle_connect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">handle_close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">handle_read</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">8192</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">writable</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">buffer</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">handle_write</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">sent</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">buffer</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">buffer</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">buffer</span><span class="p">[</span><span class="n">sent</span><span class="p">:]</span>
<span class="n">client</span> <span class="o">=</span> <span class="n">HTTPClient</span><span class="p">(</span><span class="s1">'www.python.org'</span><span class="p">,</span> <span class="s1">'/'</span><span class="p">)</span>
<span class="n">asyncore</span><span class="o">.</span><span class="n">loop</span><span class="p">()</span>
</code></pre></div><div class="section" id="asyncore-example-basic-echo-server"><h2><span class="yiyi-st" id="yiyi-130">18.6.2. asyncore示例基本echo服务器</span></h2><p><span class="yiyi-st" id="yiyi-131">这里是一个基本的回显服务器,它使用<a class="reference internal" href="#asyncore.dispatcher" title="asyncore.dispatcher"><code class="xref py py-class docutils literal"><span class="pre">dispatcher</span></code></a>类接受连接并将传入连接分派给处理程序:</span></p><pre><code class="language-python"><span></span><span class="kn">import</span> <span class="nn">asyncore</span>
<span class="k">class</span> <span class="nc">EchoHandler</span><span class="p">(</span><span class="n">asyncore</span><span class="o">.</span><span class="n">dispatcher_with_send</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">handle_read</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">8192</span><span class="p">)</span>
<span class="k">if</span> <span class="n">data</span><span class="p">:</span>
<span class="bp">self</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="k">class</span> <span class="nc">EchoServer</span><span class="p">(</span><span class="n">asyncore</span><span class="o">.</span><span class="n">dispatcher</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">):</span>
<span class="n">asyncore</span><span class="o">.</span><span class="n">dispatcher</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">create_socket</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">set_reuse_addr</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
<span class="bp">self</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">handle_accepted</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sock</span><span class="p">,</span> <span class="n">addr</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Incoming connection from </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="nb">repr</span><span class="p">(</span><span class="n">addr</span><span class="p">))</span>
<span class="n">handler</span> <span class="o">=</span> <span class="n">EchoHandler</span><span class="p">(</span><span class="n">sock</span><span class="p">)</span>
<span class="n">server</span> <span class="o">=</span> <span class="n">EchoServer</span><span class="p">(</span><span class="s1">'localhost'</span><span class="p">,</span> <span class="mi">8080</span><span class="p">)</span>
<span class="n">asyncore</span><span class="o">.</span><span class="n">loop</span><span class="p">()</span>
</code></pre></div></div></div>