769 lines
86 KiB
HTML
769 lines
86 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
|
||
<head>
|
||
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||
|
||
<title>socketserver --- 用于网络服务器的框架 — Python 3.8.20 文档</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
||
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||
|
||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||
<script src="../_static/jquery.js"></script>
|
||
<script src="../_static/underscore.js"></script>
|
||
<script src="../_static/doctools.js"></script>
|
||
<script src="../_static/language_data.js"></script>
|
||
<script src="../_static/translations.js"></script>
|
||
|
||
<script src="../_static/sidebar.js"></script>
|
||
|
||
<link rel="search" type="application/opensearchdescription+xml"
|
||
title="在 Python 3.8.20 文档 中搜索"
|
||
href="../_static/opensearch.xml"/>
|
||
<link rel="author" title="关于这些文档" href="../about.html" />
|
||
<link rel="index" title="索引" href="../genindex.html" />
|
||
<link rel="search" title="搜索" href="../search.html" />
|
||
<link rel="copyright" title="版权所有" href="../copyright.html" />
|
||
<link rel="next" title="http.server --- HTTP 服务器" href="http.server.html" />
|
||
<link rel="prev" title="uuid --- RFC 4122 定义的UUID对象" href="uuid.html" />
|
||
<link rel="canonical" href="https://docs.python.org/3/library/socketserver.html" />
|
||
|
||
|
||
|
||
|
||
|
||
<style>
|
||
@media only screen {
|
||
table.full-width-table {
|
||
width: 100%;
|
||
}
|
||
}
|
||
</style>
|
||
<link rel="shortcut icon" type="image/png" href="../_static/py.svg" />
|
||
<script type="text/javascript" src="../_static/copybutton.js"></script>
|
||
<script type="text/javascript" src="../_static/menu.js"></script>
|
||
|
||
</head>
|
||
<body>
|
||
<div class="mobile-nav">
|
||
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
|
||
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu" />
|
||
<label for="menuToggler" class="toggler__label">
|
||
<span></span>
|
||
</label>
|
||
<nav class="nav-content" role="navigation">
|
||
<a href="https://www.python.org/" class="nav-logo">
|
||
<img src="../_static/py.svg" alt="Logo"/>
|
||
</a>
|
||
<div class="version_switcher_placeholder"></div>
|
||
<form role="search" class="search" action="../search.html" method="get">
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
|
||
<path fill-rule="nonzero"
|
||
d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="#444"></path>
|
||
</svg>
|
||
<input type="text" name="q" aria-label="快速搜索"/>
|
||
<input type="submit" value="转向"/>
|
||
</form>
|
||
</nav>
|
||
<div class="menu-wrapper">
|
||
<nav class="menu" role="navigation" aria-label="main navigation">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<h3><a href="../contents.html">目录</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">socketserver</span></code> --- 用于网络服务器的框架</a><ul>
|
||
<li><a class="reference internal" href="#server-creation-notes">服务器创建的说明</a></li>
|
||
<li><a class="reference internal" href="#server-objects">Server 对象</a></li>
|
||
<li><a class="reference internal" href="#request-handler-objects">请求处理器对象</a></li>
|
||
<li><a class="reference internal" href="#examples">例子</a><ul>
|
||
<li><a class="reference internal" href="#socketserver-tcpserver-example"><code class="xref py py-class docutils literal notranslate"><span class="pre">socketserver.TCPServer</span></code> 示例</a></li>
|
||
<li><a class="reference internal" href="#socketserver-udpserver-example"><code class="xref py py-class docutils literal notranslate"><span class="pre">socketserver.UDPServer</span></code> 示例</a></li>
|
||
<li><a class="reference internal" href="#asynchronous-mixins">异步混合类</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>上一个主题</h4>
|
||
<p class="topless"><a href="uuid.html"
|
||
title="上一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">uuid</span></code> --- <strong>RFC 4122</strong> 定义的UUID对象</a></p>
|
||
<h4>下一个主题</h4>
|
||
<p class="topless"><a href="http.server.html"
|
||
title="下一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">http.server</span></code> --- HTTP 服务器</a></p>
|
||
<div role="note" aria-label="source link">
|
||
<h3>本页</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">报告 Bug</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.8/Doc/library/socketserver.rst"
|
||
rel="nofollow">显示源代码
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="outdated-warning" style="padding: .5em; text-align: center; background-color: #FFBABA; color: #6A0E0E;">
|
||
这个文档所针对的是一个已不再受支持的 Python 旧版本。
|
||
你应当升级版本,并阅读
|
||
<a href="/3/library/socketserver.html"> Python 当前稳定版本的文档</a>.
|
||
</div>
|
||
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>导航</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="总目录"
|
||
accesskey="I">索引</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python 模块索引"
|
||
>模块</a> |</li>
|
||
<li class="right" >
|
||
<a href="http.server.html" title="http.server --- HTTP 服务器"
|
||
accesskey="N">下一页</a> |</li>
|
||
<li class="right" >
|
||
<a href="uuid.html" title="uuid --- RFC 4122 定义的UUID对象"
|
||
accesskey="P">上一页</a> |</li>
|
||
|
||
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.8.20 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" >Python 标准库</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="internet.html" accesskey="U">互联网协议和支持</a> »</li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
|
||
<input type="submit" value="转向" />
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section id="module-socketserver">
|
||
<span id="socketserver-a-framework-for-network-servers"></span><h1><a class="reference internal" href="#module-socketserver" title="socketserver: A framework for network servers."><code class="xref py py-mod docutils literal notranslate"><span class="pre">socketserver</span></code></a> --- 用于网络服务器的框架<a class="headerlink" href="#module-socketserver" title="永久链接至标题">¶</a></h1>
|
||
<p><strong>源代码:</strong> <a class="reference external" href="https://github.com/python/cpython/tree/3.8/Lib/socketserver.py">Lib/socketserver.py</a></p>
|
||
<hr class="docutils" />
|
||
<p><a class="reference internal" href="#module-socketserver" title="socketserver: A framework for network servers."><code class="xref py py-mod docutils literal notranslate"><span class="pre">socketserver</span></code></a> 模块简化了编写网络服务器的任务。</p>
|
||
<p>该模块具有四个基础实体服务器类:</p>
|
||
<dl class="class">
|
||
<dt id="socketserver.TCPServer">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">TCPServer</code><span class="sig-paren">(</span><em class="sig-param">server_address</em>, <em class="sig-param">RequestHandlerClass</em>, <em class="sig-param">bind_and_activate=True</em><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.TCPServer" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>This uses the Internet TCP protocol, which provides for
|
||
continuous streams of data between the client and server.
|
||
If <em>bind_and_activate</em> is true, the constructor automatically attempts to
|
||
invoke <a class="reference internal" href="#socketserver.BaseServer.server_bind" title="socketserver.BaseServer.server_bind"><code class="xref py py-meth docutils literal notranslate"><span class="pre">server_bind()</span></code></a> and
|
||
<a class="reference internal" href="#socketserver.BaseServer.server_activate" title="socketserver.BaseServer.server_activate"><code class="xref py py-meth docutils literal notranslate"><span class="pre">server_activate()</span></code></a>. The other parameters are passed to
|
||
the <a class="reference internal" href="#socketserver.BaseServer" title="socketserver.BaseServer"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseServer</span></code></a> base class.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="socketserver.UDPServer">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">UDPServer</code><span class="sig-paren">(</span><em class="sig-param">server_address</em>, <em class="sig-param">RequestHandlerClass</em>, <em class="sig-param">bind_and_activate=True</em><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.UDPServer" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>该类使用数据包,即一系列离散的信息分包,它们可能会无序地到达或在传输中丢失。 该类的形参与 <a class="reference internal" href="#socketserver.TCPServer" title="socketserver.TCPServer"><code class="xref py py-class docutils literal notranslate"><span class="pre">TCPServer</span></code></a> 的相同。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="socketserver.UnixStreamServer">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">UnixStreamServer</code><span class="sig-paren">(</span><em class="sig-param">server_address</em>, <em class="sig-param">RequestHandlerClass</em>, <em class="sig-param">bind_and_activate=True</em><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.UnixStreamServer" title="永久链接至目标">¶</a></dt>
|
||
<dt id="socketserver.UnixDatagramServer">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">UnixDatagramServer</code><span class="sig-paren">(</span><em class="sig-param">server_address</em>, <em class="sig-param">RequestHandlerClass</em>, <em class="sig-param">bind_and_activate=True</em><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.UnixDatagramServer" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>这两个更常用的类与 TCP 和 UDP 类相似,但使用 Unix 域套接字;它们在非 Unix 系统平台上不可用。 它们的形参与 <a class="reference internal" href="#socketserver.TCPServer" title="socketserver.TCPServer"><code class="xref py py-class docutils literal notranslate"><span class="pre">TCPServer</span></code></a> 的相同。</p>
|
||
</dd></dl>
|
||
|
||
<p>这四个类会 <em class="dfn">同步地</em> 处理请求;每个请求必须完成才能开始下一个请求。 这就不适用于每个请求要耗费很长时间来完成的情况,或者因为它需要大量的计算,又或者它返回了大量的数据而客户端处理起来很缓慢。 解决方案是创建单独的进程或线程来处理每个请求;<a class="reference internal" href="#socketserver.ForkingMixIn" title="socketserver.ForkingMixIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ForkingMixIn</span></code></a> 和 <a class="reference internal" href="#socketserver.ThreadingMixIn" title="socketserver.ThreadingMixIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadingMixIn</span></code></a> 混合类可以被用于支持异步行为。</p>
|
||
<p>创建一个服务器需要分几个步骤进行。 首先,你必须通过子类化 <a class="reference internal" href="#socketserver.BaseRequestHandler" title="socketserver.BaseRequestHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseRequestHandler</span></code></a> 类并重载其 <a class="reference internal" href="#socketserver.BaseRequestHandler.handle" title="socketserver.BaseRequestHandler.handle"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle()</span></code></a> 方法来创建一个请求处理器类;这个方法将处理传入的请求。 其次,你必须实例化某个服务器类,将服务器地址和请求处理器类传给它。 建议在 <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> 语句中使用该服务器。 然后再调用服务器对象的 <a class="reference internal" href="#socketserver.BaseServer.handle_request" title="socketserver.BaseServer.handle_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle_request()</span></code></a> 或 <a class="reference internal" href="#socketserver.BaseServer.serve_forever" title="socketserver.BaseServer.serve_forever"><code class="xref py py-meth docutils literal notranslate"><span class="pre">serve_forever()</span></code></a> 方法来处理一个或多个请求。 最后,调用 <a class="reference internal" href="#socketserver.BaseServer.server_close" title="socketserver.BaseServer.server_close"><code class="xref py py-meth docutils literal notranslate"><span class="pre">server_close()</span></code></a> 来关闭套接字(除非你使用了 <code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code> 语句)。</p>
|
||
<p>当从 <a class="reference internal" href="#socketserver.ThreadingMixIn" title="socketserver.ThreadingMixIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadingMixIn</span></code></a> 继承线程连接行为时,你应当显式地声明你希望在突然关机时你的线程采取何种行为。 <a class="reference internal" href="#socketserver.ThreadingMixIn" title="socketserver.ThreadingMixIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadingMixIn</span></code></a> 类定义了一个属性 <em>daemon_threads</em>,它指明服务器是否应当等待线程终止。 如果你希望线程能自主行动你应当显式地设置这个旗标;默认值为 <a class="reference internal" href="constants.html#False" title="False"><code class="xref py py-const docutils literal notranslate"><span class="pre">False</span></code></a>,表示 Python 将不会在 <a class="reference internal" href="#socketserver.ThreadingMixIn" title="socketserver.ThreadingMixIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadingMixIn</span></code></a> 所创建的所有线程都退出之前退出。</p>
|
||
<p>服务器类具有同样的外部方法和属性,无论它们使用哪种网络协议。</p>
|
||
<section id="server-creation-notes">
|
||
<h2>服务器创建的说明<a class="headerlink" href="#server-creation-notes" title="永久链接至标题">¶</a></h2>
|
||
<p>在继承图中有五个类,其中四个代表四种类型的同步服务器:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="o">+------------+</span>
|
||
<span class="o">|</span> <span class="n">BaseServer</span> <span class="o">|</span>
|
||
<span class="o">+------------+</span>
|
||
<span class="o">|</span>
|
||
<span class="n">v</span>
|
||
<span class="o">+-----------+</span> <span class="o">+------------------+</span>
|
||
<span class="o">|</span> <span class="n">TCPServer</span> <span class="o">|------->|</span> <span class="n">UnixStreamServer</span> <span class="o">|</span>
|
||
<span class="o">+-----------+</span> <span class="o">+------------------+</span>
|
||
<span class="o">|</span>
|
||
<span class="n">v</span>
|
||
<span class="o">+-----------+</span> <span class="o">+--------------------+</span>
|
||
<span class="o">|</span> <span class="n">UDPServer</span> <span class="o">|------->|</span> <span class="n">UnixDatagramServer</span> <span class="o">|</span>
|
||
<span class="o">+-----------+</span> <span class="o">+--------------------+</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>请注意 <a class="reference internal" href="#socketserver.UnixDatagramServer" title="socketserver.UnixDatagramServer"><code class="xref py py-class docutils literal notranslate"><span class="pre">UnixDatagramServer</span></code></a> 派生自 <a class="reference internal" href="#socketserver.UDPServer" title="socketserver.UDPServer"><code class="xref py py-class docutils literal notranslate"><span class="pre">UDPServer</span></code></a>,而不是 <a class="reference internal" href="#socketserver.UnixStreamServer" title="socketserver.UnixStreamServer"><code class="xref py py-class docutils literal notranslate"><span class="pre">UnixStreamServer</span></code></a> --- IP 和 Unix 流服务器的唯一区别是地址族,它会在两种 Unix 服务器类中简单地重复。</p>
|
||
<dl class="class">
|
||
<dt id="socketserver.ForkingMixIn">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">ForkingMixIn</code><a class="headerlink" href="#socketserver.ForkingMixIn" title="永久链接至目标">¶</a></dt>
|
||
<dt id="socketserver.ThreadingMixIn">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">ThreadingMixIn</code><a class="headerlink" href="#socketserver.ThreadingMixIn" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>每种服务器类型的分叉和线程版本都可以使用这些混合类来创建。 例如,<a class="reference internal" href="#socketserver.ThreadingUDPServer" title="socketserver.ThreadingUDPServer"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadingUDPServer</span></code></a> 的创建方式如下:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">ThreadingUDPServer</span><span class="p">(</span><span class="n">ThreadingMixIn</span><span class="p">,</span> <span class="n">UDPServer</span><span class="p">):</span>
|
||
<span class="k">pass</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>混合类先出现,因为它重载了 <a class="reference internal" href="#socketserver.UDPServer" title="socketserver.UDPServer"><code class="xref py py-class docutils literal notranslate"><span class="pre">UDPServer</span></code></a> 中定义的一个方法。 设置各种属性也会改变下层服务器机制的行为。</p>
|
||
<p><a class="reference internal" href="#socketserver.ForkingMixIn" title="socketserver.ForkingMixIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ForkingMixIn</span></code></a> 和下文提及的分叉类仅在支持 <a class="reference internal" href="os.html#os.fork" title="os.fork"><code class="xref py py-func docutils literal notranslate"><span class="pre">fork()</span></code></a> 的 POSIX 系统平台上可用。</p>
|
||
<p><code class="xref py py-meth docutils literal notranslate"><span class="pre">socketserver.ForkingMixIn.server_close()</span></code> 会等待直到所有子进程完成,除非 <code class="xref py py-attr docutils literal notranslate"><span class="pre">socketserver.ForkingMixIn.block_on_close</span></code> 属性为假值。</p>
|
||
<p><code class="xref py py-meth docutils literal notranslate"><span class="pre">socketserver.ThreadingMixIn.server_close()</span></code> 会等待直到所有非守护类线程完成,除非 <code class="xref py py-attr docutils literal notranslate"><span class="pre">socketserver.ThreadingMixIn.block_on_close</span></code> 属性为假值。 请将 <code class="xref py py-data docutils literal notranslate"><span class="pre">ThreadingMixIn.daemon_threads</span></code> 设为 <code class="docutils literal notranslate"><span class="pre">True</span></code> 来使用守护类线程以便不等待线完成。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.7 版更改: </span><code class="xref py py-meth docutils literal notranslate"><span class="pre">socketserver.ForkingMixIn.server_close()</span></code> 和 <code class="xref py py-meth docutils literal notranslate"><span class="pre">socketserver.ThreadingMixIn.server_close()</span></code> 现在会等待直到所有子进程和非守护类线程完成。 请新增一个 <code class="xref py py-attr docutils literal notranslate"><span class="pre">socketserver.ForkingMixIn.block_on_close</span></code> 类属性来选择 3.7 版之前的行为。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="socketserver.ForkingTCPServer">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">ForkingTCPServer</code><a class="headerlink" href="#socketserver.ForkingTCPServer" title="永久链接至目标">¶</a></dt>
|
||
<dt id="socketserver.ForkingUDPServer">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">ForkingUDPServer</code><a class="headerlink" href="#socketserver.ForkingUDPServer" title="永久链接至目标">¶</a></dt>
|
||
<dt id="socketserver.ThreadingTCPServer">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">ThreadingTCPServer</code><a class="headerlink" href="#socketserver.ThreadingTCPServer" title="永久链接至目标">¶</a></dt>
|
||
<dt id="socketserver.ThreadingUDPServer">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">ThreadingUDPServer</code><a class="headerlink" href="#socketserver.ThreadingUDPServer" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>这些类都是使用混合类来预定义的。</p>
|
||
</dd></dl>
|
||
|
||
<p>要实现一个服务,你必须从 <a class="reference internal" href="#socketserver.BaseRequestHandler" title="socketserver.BaseRequestHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseRequestHandler</span></code></a> 派生一个类并重定义其 <a class="reference internal" href="#socketserver.BaseRequestHandler.handle" title="socketserver.BaseRequestHandler.handle"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle()</span></code></a> 方法。 然后你可以通过组合某种服务器类型与你的请求处理器类来运行各种版本的服务。 请求处理器类对于数据报和流服务必须是不相同的。 这可以通过使用处理器子类 <a class="reference internal" href="#socketserver.StreamRequestHandler" title="socketserver.StreamRequestHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">StreamRequestHandler</span></code></a> 或 <a class="reference internal" href="#socketserver.DatagramRequestHandler" title="socketserver.DatagramRequestHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">DatagramRequestHandler</span></code></a> 来隐藏。</p>
|
||
<p>当然,你仍然需要动点脑筋! 举例来说,如果服务包含可能被不同请求所修改的内存状态则使用分叉服务器是没有意义的,因为在子进程中的修改将永远不会触及保存在父进程中的初始状态并传递到各个子进程。 在这种情况下,你可以使用线程服务器,但你可能必须使用锁来保护共享数据的一致性。</p>
|
||
<p>另一方面,如果你是在编写一个所有数据保存在外部(例如文件系统)的 HTTP 服务器,同步类实际上将在正在处理某个请求的时候“失聪” -- 如果某个客户端在接收它所请求的所有数据时很缓慢这可能会是非常长的时间。 这时线程或分叉服务器会更为适用。</p>
|
||
<p>在某些情况下,合适的做法是同步地处理请求的一部分,但根据请求数据在分叉的子进程中完成处理。 这可以通过使用一个同步服务器并在请求处理器类 <a class="reference internal" href="#socketserver.BaseRequestHandler.handle" title="socketserver.BaseRequestHandler.handle"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle()</span></code></a> 中进行显式分叉来实现。</p>
|
||
<p>还有一种可以在既不支持线程也不支持 <a class="reference internal" href="os.html#os.fork" title="os.fork"><code class="xref py py-func docutils literal notranslate"><span class="pre">fork()</span></code></a> 的环境(或者对于本服务来说这两者开销过大或是不适用)中处理多个同时请求的方式是维护一个显式的部分完成的请求表并使用 <a class="reference internal" href="selectors.html#module-selectors" title="selectors: High-level I/O multiplexing."><code class="xref py py-mod docutils literal notranslate"><span class="pre">selectors</span></code></a> 来决定接下来要处理哪个请求(或者是否要处理一个新传入的请求)。 这对于流服务来说特别重要,因为每个客户端可能会连接很长的时间(如果不能使用线程或子进程)。 请参阅 <a class="reference internal" href="asyncore.html#module-asyncore" title="asyncore: A base class for developing asynchronous socket handling services."><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncore</span></code></a> 来了解另一种管理方式。</p>
|
||
</section>
|
||
<section id="server-objects">
|
||
<h2>Server 对象<a class="headerlink" href="#server-objects" title="永久链接至标题">¶</a></h2>
|
||
<dl class="class">
|
||
<dt id="socketserver.BaseServer">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">BaseServer</code><span class="sig-paren">(</span><em class="sig-param">server_address</em>, <em class="sig-param">RequestHandlerClass</em><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>这是本模块中所有 Server 对象的超类。 它定义了下文给出的接口,但没有实现大部分的方法,它们应在子类中实现。 两个形参存储在对应的 <a class="reference internal" href="#socketserver.BaseServer.server_address" title="socketserver.BaseServer.server_address"><code class="xref py py-attr docutils literal notranslate"><span class="pre">server_address</span></code></a> 和 <a class="reference internal" href="#socketserver.BaseServer.RequestHandlerClass" title="socketserver.BaseServer.RequestHandlerClass"><code class="xref py py-attr docutils literal notranslate"><span class="pre">RequestHandlerClass</span></code></a> 属性中。</p>
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.fileno">
|
||
<code class="sig-name descname">fileno</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.fileno" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>返回服务器正在监听的套接字的以整数表示的文件描述符。 此函数最常被传递给 <a class="reference internal" href="selectors.html#module-selectors" title="selectors: High-level I/O multiplexing."><code class="xref py py-mod docutils literal notranslate"><span class="pre">selectors</span></code></a>,以允许在同一进程中监控多个服务器。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.handle_request">
|
||
<code class="sig-name descname">handle_request</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.handle_request" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>处理单个请求。 此函数会依次调用下列方法: <a class="reference internal" href="#socketserver.BaseServer.get_request" title="socketserver.BaseServer.get_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">get_request()</span></code></a>, <a class="reference internal" href="#socketserver.BaseServer.verify_request" title="socketserver.BaseServer.verify_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">verify_request()</span></code></a> 和 <a class="reference internal" href="#socketserver.BaseServer.process_request" title="socketserver.BaseServer.process_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">process_request()</span></code></a>。 如果用户提供的处理器类的 <a class="reference internal" href="#socketserver.BaseRequestHandler.handle" title="socketserver.BaseRequestHandler.handle"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle()</span></code></a> 方法引发了异常,则将调用服务器的 <a class="reference internal" href="#socketserver.BaseServer.handle_error" title="socketserver.BaseServer.handle_error"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle_error()</span></code></a> 方法。 如果在 <a class="reference internal" href="#socketserver.BaseServer.timeout" title="socketserver.BaseServer.timeout"><code class="xref py py-attr docutils literal notranslate"><span class="pre">timeout</span></code></a> 秒内未接收到请求,将会调用 <a class="reference internal" href="#socketserver.BaseServer.handle_timeout" title="socketserver.BaseServer.handle_timeout"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle_timeout()</span></code></a> 并将返回 <a class="reference internal" href="#socketserver.BaseServer.handle_request" title="socketserver.BaseServer.handle_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle_request()</span></code></a>。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.serve_forever">
|
||
<code class="sig-name descname">serve_forever</code><span class="sig-paren">(</span><em class="sig-param">poll_interval=0.5</em><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.serve_forever" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>对请求进行处理直至收到显式的 <a class="reference internal" href="#socketserver.BaseServer.shutdown" title="socketserver.BaseServer.shutdown"><code class="xref py py-meth docutils literal notranslate"><span class="pre">shutdown()</span></code></a> 请求。 每隔 <em>poll_interval</em> 秒对 shutdown 进行轮询。 忽略 <a class="reference internal" href="#socketserver.BaseServer.timeout" title="socketserver.BaseServer.timeout"><code class="xref py py-attr docutils literal notranslate"><span class="pre">timeout</span></code></a> 属性。 它还会调用 <a class="reference internal" href="#socketserver.BaseServer.service_actions" title="socketserver.BaseServer.service_actions"><code class="xref py py-meth docutils literal notranslate"><span class="pre">service_actions()</span></code></a>,这可被子类或混合类用来提供某个给定服务的专属操作。 例如,<a class="reference internal" href="#socketserver.ForkingMixIn" title="socketserver.ForkingMixIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ForkingMixIn</span></code></a> 类使用 <a class="reference internal" href="#socketserver.BaseServer.service_actions" title="socketserver.BaseServer.service_actions"><code class="xref py py-meth docutils literal notranslate"><span class="pre">service_actions()</span></code></a> 来清理僵尸子进程。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.3 版更改: </span>将 <code class="docutils literal notranslate"><span class="pre">service_actions</span></code> 调用添加到 <code class="docutils literal notranslate"><span class="pre">serve_forever</span></code> 方法。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.service_actions">
|
||
<code class="sig-name descname">service_actions</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.service_actions" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>此方法会在 the <a class="reference internal" href="#socketserver.BaseServer.serve_forever" title="socketserver.BaseServer.serve_forever"><code class="xref py py-meth docutils literal notranslate"><span class="pre">serve_forever()</span></code></a> 循环中被调用。 此方法可被子类或混合类所重载以执行某个给定服务的专属操作,例如清理操作。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.3 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.shutdown">
|
||
<code class="sig-name descname">shutdown</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.shutdown" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>通知 <a class="reference internal" href="#socketserver.BaseServer.serve_forever" title="socketserver.BaseServer.serve_forever"><code class="xref py py-meth docutils literal notranslate"><span class="pre">serve_forever()</span></code></a> 循环停止并等待它完成。 <a class="reference internal" href="#socketserver.BaseServer.shutdown" title="socketserver.BaseServer.shutdown"><code class="xref py py-meth docutils literal notranslate"><span class="pre">shutdown()</span></code></a> 必须在 <a class="reference internal" href="#socketserver.BaseServer.serve_forever" title="socketserver.BaseServer.serve_forever"><code class="xref py py-meth docutils literal notranslate"><span class="pre">serve_forever()</span></code></a> 运行于不同线程时被调用否则它将发生死锁。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.server_close">
|
||
<code class="sig-name descname">server_close</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.server_close" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>清理服务器。 此方法可被重载。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="socketserver.BaseServer.address_family">
|
||
<code class="sig-name descname">address_family</code><a class="headerlink" href="#socketserver.BaseServer.address_family" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>服务器套接字所属的协议族。 常见的例子有 <a class="reference internal" href="socket.html#socket.AF_INET" title="socket.AF_INET"><code class="xref py py-const docutils literal notranslate"><span class="pre">socket.AF_INET</span></code></a> 和 <a class="reference internal" href="socket.html#socket.AF_UNIX" title="socket.AF_UNIX"><code class="xref py py-const docutils literal notranslate"><span class="pre">socket.AF_UNIX</span></code></a>。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="socketserver.BaseServer.RequestHandlerClass">
|
||
<code class="sig-name descname">RequestHandlerClass</code><a class="headerlink" href="#socketserver.BaseServer.RequestHandlerClass" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>用户提供的请求处理器类;将为每个请求创建该类的实例。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="socketserver.BaseServer.server_address">
|
||
<code class="sig-name descname">server_address</code><a class="headerlink" href="#socketserver.BaseServer.server_address" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>The address on which the server is listening. The format of addresses varies
|
||
depending on the protocol family;
|
||
see the documentation for the <a class="reference internal" href="socket.html#module-socket" title="socket: Low-level networking interface."><code class="xref py py-mod docutils literal notranslate"><span class="pre">socket</span></code></a> module
|
||
for details. For Internet protocols, this is a tuple containing a string giving
|
||
the address, and an integer port number: <code class="docutils literal notranslate"><span class="pre">('127.0.0.1',</span> <span class="pre">80)</span></code>, for example.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="socketserver.BaseServer.socket">
|
||
<code class="sig-name descname">socket</code><a class="headerlink" href="#socketserver.BaseServer.socket" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>将由服务器用于监听入站请求的套接字对象。</p>
|
||
</dd></dl>
|
||
|
||
<p>服务器类支持下列类变量:</p>
|
||
<dl class="attribute">
|
||
<dt id="socketserver.BaseServer.allow_reuse_address">
|
||
<code class="sig-name descname">allow_reuse_address</code><a class="headerlink" href="#socketserver.BaseServer.allow_reuse_address" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>服务器是否要允许地址的重用。 默认值为 <a class="reference internal" href="constants.html#False" title="False"><code class="xref py py-const docutils literal notranslate"><span class="pre">False</span></code></a>,并可在子类中设置以改变策略。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="socketserver.BaseServer.request_queue_size">
|
||
<code class="sig-name descname">request_queue_size</code><a class="headerlink" href="#socketserver.BaseServer.request_queue_size" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>请求队列的长度。 如果处理单个请求要花费很长的时间,则当服务器正忙时到达的任何请求都会被加入队列,最多加入 <a class="reference internal" href="#socketserver.BaseServer.request_queue_size" title="socketserver.BaseServer.request_queue_size"><code class="xref py py-attr docutils literal notranslate"><span class="pre">request_queue_size</span></code></a> 个请求。 一旦队列被加满,来自客户端的更多请求将收到 "Connection denied" 错误。 默认值为 5,但可在子类中重载。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="socketserver.BaseServer.socket_type">
|
||
<code class="sig-name descname">socket_type</code><a class="headerlink" href="#socketserver.BaseServer.socket_type" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>服务器使用的套接字类型;常见的有 <a class="reference internal" href="socket.html#socket.SOCK_STREAM" title="socket.SOCK_STREAM"><code class="xref py py-const docutils literal notranslate"><span class="pre">socket.SOCK_STREAM</span></code></a> 和 <a class="reference internal" href="socket.html#socket.SOCK_DGRAM" title="socket.SOCK_DGRAM"><code class="xref py py-const docutils literal notranslate"><span class="pre">socket.SOCK_DGRAM</span></code></a> 这两个值。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="attribute">
|
||
<dt id="socketserver.BaseServer.timeout">
|
||
<code class="sig-name descname">timeout</code><a class="headerlink" href="#socketserver.BaseServer.timeout" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>超时限制,以秒数表示,或者如果不限制超时则为 <a class="reference internal" href="constants.html#None" title="None"><code class="xref py py-const docutils literal notranslate"><span class="pre">None</span></code></a>。 如果在超时限制期间没有收到 <a class="reference internal" href="#socketserver.BaseServer.handle_request" title="socketserver.BaseServer.handle_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle_request()</span></code></a>,则会调用 <a class="reference internal" href="#socketserver.BaseServer.handle_timeout" title="socketserver.BaseServer.handle_timeout"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle_timeout()</span></code></a> 方法。</p>
|
||
</dd></dl>
|
||
|
||
<p>有多个服务器方法可被服务器基类的子类例如 <a class="reference internal" href="#socketserver.TCPServer" title="socketserver.TCPServer"><code class="xref py py-class docutils literal notranslate"><span class="pre">TCPServer</span></code></a> 所重载;这些方法对服务器对象的外部用户来说并无用处。</p>
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.finish_request">
|
||
<code class="sig-name descname">finish_request</code><span class="sig-paren">(</span><em class="sig-param">request</em>, <em class="sig-param">client_address</em><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.finish_request" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>通过实例化 <a class="reference internal" href="#socketserver.BaseServer.RequestHandlerClass" title="socketserver.BaseServer.RequestHandlerClass"><code class="xref py py-attr docutils literal notranslate"><span class="pre">RequestHandlerClass</span></code></a> 并调用其 <a class="reference internal" href="#socketserver.BaseRequestHandler.handle" title="socketserver.BaseRequestHandler.handle"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle()</span></code></a> 方法来实际处理请求。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.get_request">
|
||
<code class="sig-name descname">get_request</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.get_request" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>必须接受来自套接字的请求,并返回一个 2 元组,其中包含用来与客户端通信的 <em>new</em> 套接字对象,以及客户端的地址。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.handle_error">
|
||
<code class="sig-name descname">handle_error</code><span class="sig-paren">(</span><em class="sig-param">request</em>, <em class="sig-param">client_address</em><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.handle_error" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>此函数会在 <a class="reference internal" href="#socketserver.BaseServer.RequestHandlerClass" title="socketserver.BaseServer.RequestHandlerClass"><code class="xref py py-attr docutils literal notranslate"><span class="pre">RequestHandlerClass</span></code></a> 实例的 <a class="reference internal" href="#socketserver.BaseRequestHandler.handle" title="socketserver.BaseRequestHandler.handle"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle()</span></code></a> 方法引发异常时被调用。 默认行为是将回溯信息打印到标准错误并继续处理其他请求。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.6 版更改: </span>现在只针对派生自 <a class="reference internal" href="exceptions.html#Exception" title="Exception"><code class="xref py py-exc docutils literal notranslate"><span class="pre">Exception</span></code></a> 类的异常调用此方法。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.handle_timeout">
|
||
<code class="sig-name descname">handle_timeout</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.handle_timeout" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>此函数会在 <a class="reference internal" href="#socketserver.BaseServer.timeout" title="socketserver.BaseServer.timeout"><code class="xref py py-attr docutils literal notranslate"><span class="pre">timeout</span></code></a> 属性被设为 <a class="reference internal" href="constants.html#None" title="None"><code class="xref py py-const docutils literal notranslate"><span class="pre">None</span></code></a> 以外的值并且在超出时限之后仍未收到请求时被调用。 分叉服务器的默认行为是收集任何已退出的子进程状态,而在线程服务器中此方法则不做任何操作。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.process_request">
|
||
<code class="sig-name descname">process_request</code><span class="sig-paren">(</span><em class="sig-param">request</em>, <em class="sig-param">client_address</em><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.process_request" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>调用 <a class="reference internal" href="#socketserver.BaseServer.finish_request" title="socketserver.BaseServer.finish_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">finish_request()</span></code></a> 来创建 <a class="reference internal" href="#socketserver.BaseServer.RequestHandlerClass" title="socketserver.BaseServer.RequestHandlerClass"><code class="xref py py-attr docutils literal notranslate"><span class="pre">RequestHandlerClass</span></code></a> 的实例。 如果需要,此函数可创建一个新的进程或线程来处理请求;<a class="reference internal" href="#socketserver.ForkingMixIn" title="socketserver.ForkingMixIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ForkingMixIn</span></code></a> 和 <a class="reference internal" href="#socketserver.ThreadingMixIn" title="socketserver.ThreadingMixIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadingMixIn</span></code></a> 类能完成此任务。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.server_activate">
|
||
<code class="sig-name descname">server_activate</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.server_activate" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>由服务器的构造器调用以激活服务器。 TCP 服务器的默认行为只是在服务器的套接字上发起调用 <a class="reference internal" href="socket.html#socket.socket.listen" title="socket.socket.listen"><code class="xref py py-meth docutils literal notranslate"><span class="pre">listen()</span></code></a>。 可以被重载。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.server_bind">
|
||
<code class="sig-name descname">server_bind</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.server_bind" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>由服务器的构造器调用以将套接字绑定到所需的地址。 可以被重载。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseServer.verify_request">
|
||
<code class="sig-name descname">verify_request</code><span class="sig-paren">(</span><em class="sig-param">request</em>, <em class="sig-param">client_address</em><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseServer.verify_request" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>必须返回一个布尔值;如果值为 <a class="reference internal" href="constants.html#True" title="True"><code class="xref py py-const docutils literal notranslate"><span class="pre">True</span></code></a>,请求将被处理。 而如果值为 <a class="reference internal" href="constants.html#False" title="False"><code class="xref py py-const docutils literal notranslate"><span class="pre">False</span></code></a>,请求将被拒绝。 此函数可被重载以实现服务器的访问控制。 默认实现总是返回 <a class="reference internal" href="constants.html#True" title="True"><code class="xref py py-const docutils literal notranslate"><span class="pre">True</span></code></a>。</p>
|
||
</dd></dl>
|
||
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.6 版更改: </span>添加了对 <a class="reference internal" href="../glossary.html#term-context-manager"><span class="xref std std-term">context manager</span></a> 协议的支持。 退出上下文管理器与调用 <a class="reference internal" href="#socketserver.BaseServer.server_close" title="socketserver.BaseServer.server_close"><code class="xref py py-meth docutils literal notranslate"><span class="pre">server_close()</span></code></a> 等效。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="request-handler-objects">
|
||
<h2>请求处理器对象<a class="headerlink" href="#request-handler-objects" title="永久链接至标题">¶</a></h2>
|
||
<dl class="class">
|
||
<dt id="socketserver.BaseRequestHandler">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">BaseRequestHandler</code><a class="headerlink" href="#socketserver.BaseRequestHandler" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>这是所有请求处理器对象的超类。 它定义了下文列出的接口。 一个实体请求处理器子类必须定义新的 <a class="reference internal" href="#socketserver.BaseRequestHandler.handle" title="socketserver.BaseRequestHandler.handle"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle()</span></code></a> 方法,并可重载任何其他方法。 对于每个请求都会创建一个新的子类的实例。</p>
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseRequestHandler.setup">
|
||
<code class="sig-name descname">setup</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseRequestHandler.setup" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>会在 <a class="reference internal" href="#socketserver.BaseRequestHandler.handle" title="socketserver.BaseRequestHandler.handle"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle()</span></code></a> 方法之前被调用以执行任何必要的初始化操作。 默认实现不执行任何操作。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseRequestHandler.handle">
|
||
<code class="sig-name descname">handle</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseRequestHandler.handle" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>此函数必须执行为请求提供服务所需的全部操作。 默认实现不执行任何操作。 它有几个可用的实例属性;请求为 <code class="xref py py-attr docutils literal notranslate"><span class="pre">self.request</span></code>;客户端地址为 <code class="xref py py-attr docutils literal notranslate"><span class="pre">self.client_address</span></code>;服务器实例为 <code class="xref py py-attr docutils literal notranslate"><span class="pre">self.server</span></code>,如果它需要访问特定服务器信息的话。</p>
|
||
<p>针对数据报或流服务的 <code class="xref py py-attr docutils literal notranslate"><span class="pre">self.request</span></code> 类型是不同的。 对于流服务,<code class="xref py py-attr docutils literal notranslate"><span class="pre">self.request</span></code> 是一个套接字对象;对于数据报服务,<code class="xref py py-attr docutils literal notranslate"><span class="pre">self.request</span></code> 是一对字符串与套接字。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="method">
|
||
<dt id="socketserver.BaseRequestHandler.finish">
|
||
<code class="sig-name descname">finish</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#socketserver.BaseRequestHandler.finish" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>在 <a class="reference internal" href="#socketserver.BaseRequestHandler.handle" title="socketserver.BaseRequestHandler.handle"><code class="xref py py-meth docutils literal notranslate"><span class="pre">handle()</span></code></a> 方法之后调用以执行任何需要的清理操作。 默认实现不执行任何操作。 如果 <a class="reference internal" href="#socketserver.BaseRequestHandler.setup" title="socketserver.BaseRequestHandler.setup"><code class="xref py py-meth docutils literal notranslate"><span class="pre">setup()</span></code></a> 引发了异常,此函数将不会被调用。</p>
|
||
</dd></dl>
|
||
|
||
</dd></dl>
|
||
|
||
<dl class="class">
|
||
<dt id="socketserver.StreamRequestHandler">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">StreamRequestHandler</code><a class="headerlink" href="#socketserver.StreamRequestHandler" title="永久链接至目标">¶</a></dt>
|
||
<dt id="socketserver.DatagramRequestHandler">
|
||
<em class="property">class </em><code class="sig-prename descclassname">socketserver.</code><code class="sig-name descname">DatagramRequestHandler</code><a class="headerlink" href="#socketserver.DatagramRequestHandler" title="永久链接至目标">¶</a></dt>
|
||
<dd><p><a class="reference internal" href="#socketserver.BaseRequestHandler" title="socketserver.BaseRequestHandler"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseRequestHandler</span></code></a> 子类重载了 <a class="reference internal" href="#socketserver.BaseRequestHandler.setup" title="socketserver.BaseRequestHandler.setup"><code class="xref py py-meth docutils literal notranslate"><span class="pre">setup()</span></code></a> 和 <a class="reference internal" href="#socketserver.BaseRequestHandler.finish" title="socketserver.BaseRequestHandler.finish"><code class="xref py py-meth docutils literal notranslate"><span class="pre">finish()</span></code></a> 方法,并提供了 <code class="xref py py-attr docutils literal notranslate"><span class="pre">self.rfile</span></code> 和 <code class="xref py py-attr docutils literal notranslate"><span class="pre">self.wfile</span></code> 属性。 <code class="xref py py-attr docutils literal notranslate"><span class="pre">self.rfile</span></code> 和 <code class="xref py py-attr docutils literal notranslate"><span class="pre">self.wfile</span></code> 属性可以被分别读取或写入,以获取请求数据或将数据返回给客户端。</p>
|
||
<p>这两个类的 <code class="xref py py-attr docutils literal notranslate"><span class="pre">rfile</span></code> 属性都支持 <a class="reference internal" href="io.html#io.BufferedIOBase" title="io.BufferedIOBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">io.BufferedIOBase</span></code></a> 可读接口,并且 <code class="xref py py-attr docutils literal notranslate"><span class="pre">DatagramRequestHandler.wfile</span></code> 还支持 <a class="reference internal" href="io.html#io.BufferedIOBase" title="io.BufferedIOBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">io.BufferedIOBase</span></code></a> 可写接口。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.6 版更改: </span><code class="xref py py-attr docutils literal notranslate"><span class="pre">StreamRequestHandler.wfile</span></code> 也支持 <a class="reference internal" href="io.html#io.BufferedIOBase" title="io.BufferedIOBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">io.BufferedIOBase</span></code></a> 可写接口。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="examples">
|
||
<h2>例子<a class="headerlink" href="#examples" title="永久链接至标题">¶</a></h2>
|
||
<section id="socketserver-tcpserver-example">
|
||
<h3><a class="reference internal" href="#socketserver.TCPServer" title="socketserver.TCPServer"><code class="xref py py-class docutils literal notranslate"><span class="pre">socketserver.TCPServer</span></code></a> 示例<a class="headerlink" href="#socketserver-tcpserver-example" title="永久链接至标题">¶</a></h3>
|
||
<p>以下是服务端:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">socketserver</span>
|
||
|
||
<span class="k">class</span> <span class="nc">MyTCPHandler</span><span class="p">(</span><span class="n">socketserver</span><span class="o">.</span><span class="n">BaseRequestHandler</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""</span>
|
||
<span class="sd"> The request handler class for our server.</span>
|
||
|
||
<span class="sd"> It is instantiated once per connection to the server, and must</span>
|
||
<span class="sd"> override the handle() method to implement communication to the</span>
|
||
<span class="sd"> client.</span>
|
||
<span class="sd"> """</span>
|
||
|
||
<span class="k">def</span> <span class="nf">handle</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="c1"># self.request is the TCP socket connected to the client</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"</span><span class="si">{}</span><span class="s2"> wrote:"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">client_address</span><span class="p">[</span><span class="mi">0</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">data</span><span class="p">)</span>
|
||
<span class="c1"># just send back the same data, but upper-cased</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="o">.</span><span class="n">upper</span><span class="p">())</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</span><span class="p">:</span>
|
||
<span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span> <span class="o">=</span> <span class="s2">"localhost"</span><span class="p">,</span> <span class="mi">9999</span>
|
||
|
||
<span class="c1"># Create the server, binding to localhost on port 9999</span>
|
||
<span class="k">with</span> <span class="n">socketserver</span><span class="o">.</span><span class="n">TCPServer</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">MyTCPHandler</span><span class="p">)</span> <span class="k">as</span> <span class="n">server</span><span class="p">:</span>
|
||
<span class="c1"># Activate the server; this will keep running until you</span>
|
||
<span class="c1"># interrupt the program with Ctrl-C</span>
|
||
<span class="n">server</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>一个使用流(通过提供标准文件接口来简化通信的文件型对象)的替代请求处理器类:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyTCPHandler</span><span class="p">(</span><span class="n">socketserver</span><span class="o">.</span><span class="n">StreamRequestHandler</span><span class="p">):</span>
|
||
|
||
<span class="k">def</span> <span class="nf">handle</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="c1"># self.rfile is a file-like object created by the handler;</span>
|
||
<span class="c1"># we can now use e.g. readline() instead of raw recv() calls</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rfile</span><span class="o">.</span><span class="n">readline</span><span class="p">()</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"</span><span class="si">{}</span><span class="s2"> wrote:"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">client_address</span><span class="p">[</span><span class="mi">0</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">data</span><span class="p">)</span>
|
||
<span class="c1"># Likewise, self.wfile is a file-like object used to write back</span>
|
||
<span class="c1"># to the client</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">wfile</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="o">.</span><span class="n">upper</span><span class="p">())</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>区别在于第二个处理器的 <code class="docutils literal notranslate"><span class="pre">readline()</span></code> 调用将多次调用 <code class="docutils literal notranslate"><span class="pre">recv()</span></code> 直至遇到一个换行符,而第一个处理器的单次 <code class="docutils literal notranslate"><span class="pre">recv()</span></code> 调用只是返回在一次 <code class="docutils literal notranslate"><span class="pre">sendall()</span></code> 调用中由客户端发送的内容。</p>
|
||
<p>以下是客户端:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">socket</span>
|
||
<span class="kn">import</span> <span class="nn">sys</span>
|
||
|
||
<span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span> <span class="o">=</span> <span class="s2">"localhost"</span><span class="p">,</span> <span class="mi">9999</span>
|
||
<span class="n">data</span> <span class="o">=</span> <span class="s2">" "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:])</span>
|
||
|
||
<span class="c1"># Create a socket (SOCK_STREAM means a TCP socket)</span>
|
||
<span class="k">with</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span> <span class="k">as</span> <span class="n">sock</span><span class="p">:</span>
|
||
<span class="c1"># Connect to server and send data</span>
|
||
<span class="n">sock</span><span class="o">.</span><span class="n">connect</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">sock</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">data</span> <span class="o">+</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="s2">"utf-8"</span><span class="p">))</span>
|
||
|
||
<span class="c1"># Receive data from the server and shut down</span>
|
||
<span class="n">received</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">),</span> <span class="s2">"utf-8"</span><span class="p">)</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Sent: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">data</span><span class="p">))</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Received: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">received</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这个示例程序的输出应该是像这样的:</p>
|
||
<p>服务器:</p>
|
||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python<span class="w"> </span>TCPServer.py
|
||
<span class="go">127.0.0.1 wrote:</span>
|
||
<span class="go">b'hello world with TCP'</span>
|
||
<span class="go">127.0.0.1 wrote:</span>
|
||
<span class="go">b'python is nice'</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>客户端:</p>
|
||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python<span class="w"> </span>TCPClient.py<span class="w"> </span>hello<span class="w"> </span>world<span class="w"> </span>with<span class="w"> </span>TCP
|
||
<span class="go">Sent: hello world with TCP</span>
|
||
<span class="go">Received: HELLO WORLD WITH TCP</span>
|
||
<span class="gp">$ </span>python<span class="w"> </span>TCPClient.py<span class="w"> </span>python<span class="w"> </span>is<span class="w"> </span>nice
|
||
<span class="go">Sent: python is nice</span>
|
||
<span class="go">Received: PYTHON IS NICE</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="socketserver-udpserver-example">
|
||
<h3><a class="reference internal" href="#socketserver.UDPServer" title="socketserver.UDPServer"><code class="xref py py-class docutils literal notranslate"><span class="pre">socketserver.UDPServer</span></code></a> 示例<a class="headerlink" href="#socketserver-udpserver-example" title="永久链接至标题">¶</a></h3>
|
||
<p>以下是服务端:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">socketserver</span>
|
||
|
||
<span class="k">class</span> <span class="nc">MyUDPHandler</span><span class="p">(</span><span class="n">socketserver</span><span class="o">.</span><span class="n">BaseRequestHandler</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""</span>
|
||
<span class="sd"> This class works similar to the TCP handler class, except that</span>
|
||
<span class="sd"> self.request consists of a pair of data and client socket, and since</span>
|
||
<span class="sd"> there is no connection the client address must be given explicitly</span>
|
||
<span class="sd"> when sending data back via sendto().</span>
|
||
<span class="sd"> """</span>
|
||
|
||
<span class="k">def</span> <span class="nf">handle</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">request</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
||
<span class="n">socket</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"</span><span class="si">{}</span><span class="s2"> wrote:"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">client_address</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
|
||
<span class="n">socket</span><span class="o">.</span><span class="n">sendto</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">upper</span><span class="p">(),</span> <span class="bp">self</span><span class="o">.</span><span class="n">client_address</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</span><span class="p">:</span>
|
||
<span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span> <span class="o">=</span> <span class="s2">"localhost"</span><span class="p">,</span> <span class="mi">9999</span>
|
||
<span class="k">with</span> <span class="n">socketserver</span><span class="o">.</span><span class="n">UDPServer</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">MyUDPHandler</span><span class="p">)</span> <span class="k">as</span> <span class="n">server</span><span class="p">:</span>
|
||
<span class="n">server</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>以下是客户端:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">socket</span>
|
||
<span class="kn">import</span> <span class="nn">sys</span>
|
||
|
||
<span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span> <span class="o">=</span> <span class="s2">"localhost"</span><span class="p">,</span> <span class="mi">9999</span>
|
||
<span class="n">data</span> <span class="o">=</span> <span class="s2">" "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:])</span>
|
||
|
||
<span class="c1"># SOCK_DGRAM is the socket type to use for UDP sockets</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">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_DGRAM</span><span class="p">)</span>
|
||
|
||
<span class="c1"># As you can see, there is no connect() call; UDP has no connections.</span>
|
||
<span class="c1"># Instead, data is directly sent to the recipient via sendto().</span>
|
||
<span class="n">sock</span><span class="o">.</span><span class="n">sendto</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">data</span> <span class="o">+</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="s2">"utf-8"</span><span class="p">),</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">received</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">),</span> <span class="s2">"utf-8"</span><span class="p">)</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Sent: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">data</span><span class="p">))</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Received: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">received</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这个示例程序的输出应该是与 TCP 服务器示例相一致的。</p>
|
||
</section>
|
||
<section id="asynchronous-mixins">
|
||
<h3>异步混合类<a class="headerlink" href="#asynchronous-mixins" title="永久链接至标题">¶</a></h3>
|
||
<p>要构建异步处理器,请使用 <a class="reference internal" href="#socketserver.ThreadingMixIn" title="socketserver.ThreadingMixIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadingMixIn</span></code></a> 和 <a class="reference internal" href="#socketserver.ForkingMixIn" title="socketserver.ForkingMixIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ForkingMixIn</span></code></a> 类。</p>
|
||
<p><a class="reference internal" href="#socketserver.ThreadingMixIn" title="socketserver.ThreadingMixIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadingMixIn</span></code></a> 类的示例:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">socket</span>
|
||
<span class="kn">import</span> <span class="nn">threading</span>
|
||
<span class="kn">import</span> <span class="nn">socketserver</span>
|
||
|
||
<span class="k">class</span> <span class="nc">ThreadedTCPRequestHandler</span><span class="p">(</span><span class="n">socketserver</span><span class="o">.</span><span class="n">BaseRequestHandler</span><span class="p">):</span>
|
||
|
||
<span class="k">def</span> <span class="nf">handle</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="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">),</span> <span class="s1">'ascii'</span><span class="p">)</span>
|
||
<span class="n">cur_thread</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">current_thread</span><span class="p">()</span>
|
||
<span class="n">response</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">(</span><span class="s2">"</span><span class="si">{}</span><span class="s2">: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">cur_thread</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">data</span><span class="p">),</span> <span class="s1">'ascii'</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">response</span><span class="p">)</span>
|
||
|
||
<span class="k">class</span> <span class="nc">ThreadedTCPServer</span><span class="p">(</span><span class="n">socketserver</span><span class="o">.</span><span class="n">ThreadingMixIn</span><span class="p">,</span> <span class="n">socketserver</span><span class="o">.</span><span class="n">TCPServer</span><span class="p">):</span>
|
||
<span class="k">pass</span>
|
||
|
||
<span class="k">def</span> <span class="nf">client</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="n">message</span><span class="p">):</span>
|
||
<span class="k">with</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span> <span class="k">as</span> <span class="n">sock</span><span class="p">:</span>
|
||
<span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="n">ip</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
|
||
<span class="n">sock</span><span class="o">.</span><span class="n">sendall</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="s1">'ascii'</span><span class="p">))</span>
|
||
<span class="n">response</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">),</span> <span class="s1">'ascii'</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Received: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">response</span><span class="p">))</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</span><span class="p">:</span>
|
||
<span class="c1"># Port 0 means to select an arbitrary unused port</span>
|
||
<span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span> <span class="o">=</span> <span class="s2">"localhost"</span><span class="p">,</span> <span class="mi">0</span>
|
||
|
||
<span class="n">server</span> <span class="o">=</span> <span class="n">ThreadedTCPServer</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">ThreadedTCPRequestHandler</span><span class="p">)</span>
|
||
<span class="k">with</span> <span class="n">server</span><span class="p">:</span>
|
||
<span class="n">ip</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">server</span><span class="o">.</span><span class="n">server_address</span>
|
||
|
||
<span class="c1"># Start a thread with the server -- that thread will then start one</span>
|
||
<span class="c1"># more thread for each request</span>
|
||
<span class="n">server_thread</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">server</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">)</span>
|
||
<span class="c1"># Exit the server thread when the main thread terminates</span>
|
||
<span class="n">server_thread</span><span class="o">.</span><span class="n">daemon</span> <span class="o">=</span> <span class="kc">True</span>
|
||
<span class="n">server_thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="s2">"Server loop running in thread:"</span><span class="p">,</span> <span class="n">server_thread</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
|
||
|
||
<span class="n">client</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="s2">"Hello World 1"</span><span class="p">)</span>
|
||
<span class="n">client</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="s2">"Hello World 2"</span><span class="p">)</span>
|
||
<span class="n">client</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="s2">"Hello World 3"</span><span class="p">)</span>
|
||
|
||
<span class="n">server</span><span class="o">.</span><span class="n">shutdown</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>这个示例程序的输出应该是像这样的:</p>
|
||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python<span class="w"> </span>ThreadedTCPServer.py
|
||
<span class="go">Server loop running in thread: Thread-1</span>
|
||
<span class="go">Received: Thread-2: Hello World 1</span>
|
||
<span class="go">Received: Thread-3: Hello World 2</span>
|
||
<span class="go">Received: Thread-4: Hello World 3</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference internal" href="#socketserver.ForkingMixIn" title="socketserver.ForkingMixIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ForkingMixIn</span></code></a> 类的使用方式是相同的,区别在于服务器将为每个请求产生一个新的进程。 仅在支持 <a class="reference internal" href="os.html#os.fork" title="os.fork"><code class="xref py py-func docutils literal notranslate"><span class="pre">fork()</span></code></a> 的 POSIX 系统平台上可用。</p>
|
||
</section>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||
<div class="sphinxsidebarwrapper">
|
||
<h3><a href="../contents.html">目录</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">socketserver</span></code> --- 用于网络服务器的框架</a><ul>
|
||
<li><a class="reference internal" href="#server-creation-notes">服务器创建的说明</a></li>
|
||
<li><a class="reference internal" href="#server-objects">Server 对象</a></li>
|
||
<li><a class="reference internal" href="#request-handler-objects">请求处理器对象</a></li>
|
||
<li><a class="reference internal" href="#examples">例子</a><ul>
|
||
<li><a class="reference internal" href="#socketserver-tcpserver-example"><code class="xref py py-class docutils literal notranslate"><span class="pre">socketserver.TCPServer</span></code> 示例</a></li>
|
||
<li><a class="reference internal" href="#socketserver-udpserver-example"><code class="xref py py-class docutils literal notranslate"><span class="pre">socketserver.UDPServer</span></code> 示例</a></li>
|
||
<li><a class="reference internal" href="#asynchronous-mixins">异步混合类</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>上一个主题</h4>
|
||
<p class="topless"><a href="uuid.html"
|
||
title="上一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">uuid</span></code> --- <strong>RFC 4122</strong> 定义的UUID对象</a></p>
|
||
<h4>下一个主题</h4>
|
||
<p class="topless"><a href="http.server.html"
|
||
title="下一章"><code class="xref py py-mod docutils literal notranslate"><span class="pre">http.server</span></code> --- HTTP 服务器</a></p>
|
||
<div role="note" aria-label="source link">
|
||
<h3>本页</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">报告 Bug</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.8/Doc/library/socketserver.rst"
|
||
rel="nofollow">显示源代码
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>导航</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="总目录"
|
||
>索引</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python 模块索引"
|
||
>模块</a> |</li>
|
||
<li class="right" >
|
||
<a href="http.server.html" title="http.server --- HTTP 服务器"
|
||
>下一页</a> |</li>
|
||
<li class="right" >
|
||
<a href="uuid.html" title="uuid --- RFC 4122 定义的UUID对象"
|
||
>上一页</a> |</li>
|
||
|
||
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.8.20 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" >Python 标准库</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="internet.html" >互联网协议和支持</a> »</li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
|
||
<input type="submit" value="转向" />
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
<div class="footer">
|
||
© <a href="../copyright.html">版权所有</a> 2001-2024, Python Software Foundation.
|
||
<br />
|
||
This page is licensed under the Python Software Foundation License Version 2.
|
||
<br />
|
||
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
|
||
<br />
|
||
|
||
<br />
|
||
|
||
The Python Software Foundation is a non-profit corporation.
|
||
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
||
<br />
|
||
<br />
|
||
|
||
最后更新于 12月 09, 2024.
|
||
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
|
||
<br />
|
||
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 2.4.4.
|
||
</div>
|
||
|
||
</body>
|
||
</html> |