💖💖💖养成每日阅读好习惯, 每天进步, 超越昨天的自己💖💖💖
愿景:输出体系化编程知识与技巧,助力软件行业发展与从业者学习减负,让编程产生更大价值。
🔎🔎🔎
Python 专栏文章: 👉👉👉Python 文章专栏大全 | 有勇气的牛排👈👈👈
大家好,我是有勇气的牛排🐮🐮🐮
有问题的小伙伴欢迎在文末评论,点赞、收藏是对我最大的支持!!!
文章目录
一、前言
Remote Procedure Call即RPC(远程方法调用),它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。并且被多重语言支持,故能在多种语言的服务器中相互调用。
RPC采用客户机/服务器模式。请求程序即为客户机,服务程序为服务端。首先由客户端发起一个远程调用并等待,然后由服务端进行处理、计算并应答,结束后进入睡眠状态,客户端继续进行运行。
二、 ServerProxy 对象
ServerProxy 实例有一个方法与 XML-RPC 服务器所接受的每个远程过程调用相对应。 调用该方法会执行一个 RPC,通过名称和参数签名来调度(例如同一个方法名可通过多个参数签名来重载)。 RPC 结束时返回一个值,它可以是适用类型的返回数据或是表示错误的 Fault 或 ProtocolError 对象。
1、简单的搭建
(1)server
from xmlrpc.server import SimpleXMLRPCServer
rpc_server = "127.0.0.1"
rpc_port = 8000
def get_name(name):
res = f"名字:{name}"
return res
server = SimpleXMLRPCServer((rpc_server, rpc_port))
print("Listening on port 8000...")
server.register_function(get_name, "get_name")
server.serve_forever()
(2)client
import xmlrpc.client
rpc_server = "127.0.0.1"
rpc_port = 8000
proxy = xmlrpc.client.ServerProxy(f"http://{rpc_server}:{rpc_port}/")
print(str(proxy.get_name("有勇气的牛排")))
2、 支持多线程
(1)server
多线程
自定义类ThreadXMLRPCServer,继承两个基类,ThreadingMixIn, SimpleXMLRPCServer
ThreadingMixIn:帮助支持多线程
SimpleXMLRPCServer:RPC支持
from xmlrpc.server import SimpleXMLRPCServer
from socketserver import ThreadingMixIn
rpc_server = "127.0.0.1"
rpc_port = 8000
class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
"""
多线程
自定义类ThreadXMLRPCServer,继承两个基类,ThreadingMixIn, SimpleXMLRPCServer
ThreadingMixIn:帮助支持多线程
SimpleXMLRPCServer:RPC支持
"""
pass
def get_name(name):
res = f"名字:{name}"
return res
if __name__ == '__main__':
server = ThreadXMLRPCServer((rpc_server, rpc_port))
print("Listening on port 8000...")
server.register_function(get_name, "get_name")
server.serve_forever()
(2)client
from xmlrpc.client import ServerProxy
rpc_server = "127.0.0.1"
rpc_port = 8000
if __name__ == '__main__':
proxy = ServerProxy(f"http://{rpc_server}:{rpc_port}/")
res = str(proxy.get_name("有勇气的牛排"))
print(res)
三、DateTime 对象
该类的初始化可以使用距离 Unix 纪元的秒数、时间元组、ISO 8601 时间/日期字符串或 datetime.datetime 实例。
server
from datetime import datetime
from xmlrpc.server import SimpleXMLRPCServer
from socketserver import ThreadingMixIn
import xmlrpc.client
rpc_server = "127.0.0.1"
rpc_port = 8000
class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
pass
def get_server_time():
today = datetime.today()
return xmlrpc.client.DateTime(today)
if __name__ == '__main__':
server = ThreadXMLRPCServer((rpc_server, rpc_port), allow_none=True)
print("Listening on port 8000...")
server.register_function(get_server_time, "get_server_time")
server.serve_forever()
client
from datetime import datetime
from xmlrpc.client import ServerProxy
rpc_server = "127.0.0.1"
rpc_port = 8000
if __name__ == '__main__':
server = ServerProxy(f"http://{rpc_server}:{rpc_port}/")
server_time = datetime.strptime(server.get_server_time().value, "%Y%m%dT%H:%M:%S")
print(server_time)

四、Binary 对象
RPC除了互相串参数外,文件也是可以传的,即上传与下载。我们这里可以使用Binary对象即可实现。
该类的初始化可以使用字节数据(可包括 NUL)。
server
from xmlrpc.server import SimpleXMLRPCServer
from socketserver import ThreadingMixIn
import xmlrpc.client
rpc_server = "127.0.0.1"
rpc_port = 8000
class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
pass
def get_file():
handle = open("test.txt", 'rb')
return xmlrpc.client.Binary(handle.read())
def put_file(data):
handle = open(f"./tmp/test.txt", "wb")
handle.write(data.data)
handle.close()
if __name__ == '__main__':
server = ThreadXMLRPCServer((rpc_server, rpc_port), allow_none=True)
print("Listening on port 8000...")
server.register_function(get_file, "get_file")
server.register_function(put_file, "put_file")
server.serve_forever()
client
from xmlrpc.client import ServerProxy
import xmlrpc.client
rpc_server = "127.0.0.1"
rpc_port = 8000
if __name__ == '__main__':
server = ServerProxy(f"http://{rpc_server}:{rpc_port}/")
put_handle = open("test.txt", 'rb')
server.put_file(xmlrpc.client.Binary(put_handle.read()))
put_handle.close()
五、报错
<Fault 1: "<class 'TypeError'>:cannot marshal None unless allow_none is enabled"
添加allow_none=True
即可
server = ThreadXMLRPCServer((rpc_server, rpc_port), allow_none=True)
<blockquote>
<p><font face="楷体,华文行楷,隶书,黑体" color="black" size="4"><strong>💖💖💖养成每日阅读好习惯, 每天进步, 超越昨天的自己💖💖💖</strong></font><br />
<font face="楷体,华文行楷,隶书,黑体" color="#9400D3" size="3"><strong>愿景:输出体系化编程知识与技巧,助力软件行业发展与从业者学习减负,让编程产生更大价值。</strong></font></p>
<p>🔎🔎🔎<br />
<strong>Python 专栏文章: 👉👉👉<a href="https://www.couragesteak.com/article/11" target="_blank">Python 文章专栏大全 | 有勇气的牛排</a>👈👈👈</strong><br />
</font></p>
</blockquote>
<p><font face="楷体,华文行楷,隶书,黑体" color="red" size="4"><strong>大家好,我是有勇气的牛排🐮🐮🐮</strong> </font><br />
<font face="楷体,华文行楷,隶书,黑体" color="blue" size="4"><strong>有问题的小伙伴欢迎在文末评论,点赞、收藏是对我最大的支持!!!</strong></font></p>
<p><h3>文章目录</h3><ul><ul><li><a href="#_12">一、前言</a></li><li><a href="#_ServerProxy__18">二、 ServerProxy 对象</a></li><ul><li><a href="#1_22">1、简单的搭建</a></li><li><a href="#2__59">2、 支持多线程</a></li></ul><li><a href="#DateTime__125">三、DateTime 对象</a></li><li><a href="#Binary__177">四、Binary 对象</a></li><li><a href="#_247">五、报错</a></li></ul></ul></p>
<h2><a id="_12"></a>一、前言</h2>
<p>Remote Procedure Call即RPC(远程方法调用),它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。并且被多重语言支持,故能在多种语言的服务器中相互调用。</p>
<p>RPC采用客户机/服务器模式。请求程序即为客户机,服务程序为服务端。首先由客户端发起一个远程调用并等待,然后由服务端进行处理、计算并应答,结束后进入睡眠状态,客户端继续进行运行。</p>
<h2><a id="_ServerProxy__18"></a>二、 ServerProxy 对象</h2>
<p>ServerProxy 实例有一个方法与 XML-RPC 服务器所接受的每个远程过程调用相对应。 调用该方法会执行一个 RPC,通过名称和参数签名来调度(例如同一个方法名可通过多个参数签名来重载)。 RPC 结束时返回一个值,它可以是适用类型的返回数据或是表示错误的 Fault 或 ProtocolError 对象。</p>
<h3><a id="1_22"></a>1、简单的搭建</h3>
<p>(1)server</p>
<pre><div class="hljs"><code class="lang-python"><span class="hljs-keyword">from</span> xmlrpc.server <span class="hljs-keyword">import</span> SimpleXMLRPCServer
rpc_server = <span class="hljs-string">"127.0.0.1"</span>
rpc_port = <span class="hljs-number">8000</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_name</span>(<span class="hljs-params">name</span>):
res = <span class="hljs-string">f"名字:<span class="hljs-subst">{name}</span>"</span>
<span class="hljs-keyword">return</span> res
server = SimpleXMLRPCServer((rpc_server, rpc_port))
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Listening on port 8000..."</span>)
server.register_function(get_name, <span class="hljs-string">"get_name"</span>)
<span class="hljs-comment"># 保持等待调用状态</span>
server.serve_forever()
</code></div></pre>
<p>(2)client</p>
<pre><div class="hljs"><code class="lang-python"><span class="hljs-keyword">import</span> xmlrpc.client
rpc_server = <span class="hljs-string">"127.0.0.1"</span>
rpc_port = <span class="hljs-number">8000</span>
proxy = xmlrpc.client.ServerProxy(<span class="hljs-string">f"http://<span class="hljs-subst">{rpc_server}</span>:<span class="hljs-subst">{rpc_port}</span>/"</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-built_in">str</span>(proxy.get_name(<span class="hljs-string">"有勇气的牛排"</span>)))
<span class="hljs-comment"># 输出:名字:有勇气的牛排</span>
</code></div></pre>
<h3><a id="2__59"></a>2、 支持多线程</h3>
<p><strong>(1)server</strong></p>
<p>多线程<br />
自定义类ThreadXMLRPCServer,继承两个基类,ThreadingMixIn, SimpleXMLRPCServer<br />
ThreadingMixIn:帮助支持多线程<br />
SimpleXMLRPCServer:RPC支持</p>
<pre><div class="hljs"><code class="lang-python"><span class="hljs-keyword">from</span> xmlrpc.server <span class="hljs-keyword">import</span> SimpleXMLRPCServer
<span class="hljs-keyword">from</span> socketserver <span class="hljs-keyword">import</span> ThreadingMixIn
rpc_server = <span class="hljs-string">"127.0.0.1"</span>
rpc_port = <span class="hljs-number">8000</span>
<span class="hljs-keyword">class</span> <span class="hljs-title class_">ThreadXMLRPCServer</span>(ThreadingMixIn, SimpleXMLRPCServer):
<span class="hljs-string">"""
多线程
自定义类ThreadXMLRPCServer,继承两个基类,ThreadingMixIn, SimpleXMLRPCServer
ThreadingMixIn:帮助支持多线程
SimpleXMLRPCServer:RPC支持
"""</span>
<span class="hljs-keyword">pass</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_name</span>(<span class="hljs-params">name</span>):
res = <span class="hljs-string">f"名字:<span class="hljs-subst">{name}</span>"</span>
<span class="hljs-keyword">return</span> res
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
<span class="hljs-comment"># 多线程 class ThreadXMLRPCServer</span>
server = ThreadXMLRPCServer((rpc_server, rpc_port))
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Listening on port 8000..."</span>)
<span class="hljs-comment"># 注册函数</span>
server.register_function(get_name, <span class="hljs-string">"get_name"</span>)
<span class="hljs-comment"># 保持等待调用状态</span>
server.serve_forever()
</code></div></pre>
<p><strong>(2)client</strong></p>
<pre><div class="hljs"><code class="lang-python"><span class="hljs-comment"># _*_ coding:utf-8 _*_</span>
<span class="hljs-keyword">from</span> xmlrpc.client <span class="hljs-keyword">import</span> ServerProxy
rpc_server = <span class="hljs-string">"127.0.0.1"</span>
rpc_port = <span class="hljs-number">8000</span>
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
<span class="hljs-comment"># 初始化服务器</span>
proxy = ServerProxy(<span class="hljs-string">f"http://<span class="hljs-subst">{rpc_server}</span>:<span class="hljs-subst">{rpc_port}</span>/"</span>)
<span class="hljs-comment"># 调用函数 get_name</span>
res = <span class="hljs-built_in">str</span>(proxy.get_name(<span class="hljs-string">"有勇气的牛排"</span>))
<span class="hljs-built_in">print</span>(res)
</code></div></pre>
<h2><a id="DateTime__125"></a>三、DateTime 对象</h2>
<p>该类的初始化可以使用距离 Unix 纪元的秒数、时间元组、ISO 8601 时间/日期字符串或 datetime.datetime 实例。</p>
<p>server</p>
<pre><div class="hljs"><code class="lang-python"><span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime
<span class="hljs-keyword">from</span> xmlrpc.server <span class="hljs-keyword">import</span> SimpleXMLRPCServer
<span class="hljs-keyword">from</span> socketserver <span class="hljs-keyword">import</span> ThreadingMixIn
<span class="hljs-keyword">import</span> xmlrpc.client
rpc_server = <span class="hljs-string">"127.0.0.1"</span>
rpc_port = <span class="hljs-number">8000</span>
<span class="hljs-keyword">class</span> <span class="hljs-title class_">ThreadXMLRPCServer</span>(ThreadingMixIn, SimpleXMLRPCServer):
<span class="hljs-keyword">pass</span>
<span class="hljs-comment"># DateTime 对象</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_server_time</span>():
today = datetime.today()
<span class="hljs-keyword">return</span> xmlrpc.client.DateTime(today)
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
<span class="hljs-comment"># 多线程 class ThreadXMLRPCServer</span>
server = ThreadXMLRPCServer((rpc_server, rpc_port), allow_none=<span class="hljs-literal">True</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Listening on port 8000..."</span>)
server.register_function(get_server_time, <span class="hljs-string">"get_server_time"</span>)
<span class="hljs-comment"># 保持等待调用状态</span>
server.serve_forever()
</code></div></pre>
<p>client</p>
<pre><div class="hljs"><code class="lang-python"><span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime
<span class="hljs-keyword">from</span> xmlrpc.client <span class="hljs-keyword">import</span> ServerProxy
rpc_server = <span class="hljs-string">"127.0.0.1"</span>
rpc_port = <span class="hljs-number">8000</span>
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
server = ServerProxy(<span class="hljs-string">f"http://<span class="hljs-subst">{rpc_server}</span>:<span class="hljs-subst">{rpc_port}</span>/"</span>)
server_time = datetime.strptime(server.get_server_time().value, <span class="hljs-string">"%Y%m%dT%H:%M:%S"</span>)
<span class="hljs-built_in">print</span>(server_time)
</code></div></pre>
<p><img src="https://static.couragesteak.com/article/79f0bf3663421ac9d1a6adf7e00b521a.png" alt="image.png" /></p>
<h2><a id="Binary__177"></a>四、Binary 对象</h2>
<p>RPC除了互相串参数外,文件也是可以传的,即上传与下载。我们这里可以使用Binary对象即可实现。</p>
<p>该类的初始化可以使用字节数据(可包括 NUL)。</p>
<p>server</p>
<pre><div class="hljs"><code class="lang-python"><span class="hljs-keyword">from</span> xmlrpc.server <span class="hljs-keyword">import</span> SimpleXMLRPCServer
<span class="hljs-keyword">from</span> socketserver <span class="hljs-keyword">import</span> ThreadingMixIn
<span class="hljs-keyword">import</span> xmlrpc.client
rpc_server = <span class="hljs-string">"127.0.0.1"</span>
rpc_port = <span class="hljs-number">8000</span>
<span class="hljs-keyword">class</span> <span class="hljs-title class_">ThreadXMLRPCServer</span>(ThreadingMixIn, SimpleXMLRPCServer):
<span class="hljs-keyword">pass</span>
<span class="hljs-comment"># 提供客户端下载文件</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_file</span>():
handle = <span class="hljs-built_in">open</span>(<span class="hljs-string">"test.txt"</span>, <span class="hljs-string">'rb'</span>)
<span class="hljs-keyword">return</span> xmlrpc.client.Binary(handle.read())
<span class="hljs-comment"># 提供客户端上传文件</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">put_file</span>(<span class="hljs-params">data</span>):
handle = <span class="hljs-built_in">open</span>(<span class="hljs-string">f"./tmp/test.txt"</span>, <span class="hljs-string">"wb"</span>)
handle.write(data.data)
handle.close()
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
<span class="hljs-comment"># 多线程 class ThreadXMLRPCServer</span>
server = ThreadXMLRPCServer((rpc_server, rpc_port), allow_none=<span class="hljs-literal">True</span>)
<span class="hljs-comment"># server = SimpleXMLRPCServer((rpc_server, rpc_port))</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Listening on port 8000..."</span>)
<span class="hljs-comment"># 注册函数</span>
server.register_function(get_file, <span class="hljs-string">"get_file"</span>)
server.register_function(put_file, <span class="hljs-string">"put_file"</span>)
<span class="hljs-comment"># 保持等待调用状态</span>
server.serve_forever()
</code></div></pre>
<p>client</p>
<pre><div class="hljs"><code class="lang-python"><span class="hljs-keyword">from</span> xmlrpc.client <span class="hljs-keyword">import</span> ServerProxy
<span class="hljs-keyword">import</span> xmlrpc.client
rpc_server = <span class="hljs-string">"127.0.0.1"</span>
rpc_port = <span class="hljs-number">8000</span>
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
server = ServerProxy(<span class="hljs-string">f"http://<span class="hljs-subst">{rpc_server}</span>:<span class="hljs-subst">{rpc_port}</span>/"</span>)
<span class="hljs-comment"># 上传文件</span>
put_handle = <span class="hljs-built_in">open</span>(<span class="hljs-string">"test.txt"</span>, <span class="hljs-string">'rb'</span>)
server.put_file(xmlrpc.client.Binary(put_handle.read()))
put_handle.close()
<span class="hljs-comment"># 下载文件</span>
<span class="hljs-comment"># get_handle = open("./tmp/test.txt", 'wb')</span>
<span class="hljs-comment"># get_handle.write(server.get_file().data)</span>
<span class="hljs-comment"># get_handle.close()</span>
</code></div></pre>
<h2><a id="_247"></a>五、报错</h2>
<p><code><Fault 1: "<class 'TypeError'>:cannot marshal None unless allow_none is enabled"</code></p>
<p>添加<code>allow_none=True</code>即可</p>
<pre><div class="hljs"><code class="lang-python">server = ThreadXMLRPCServer((rpc_server, rpc_port), allow_none=<span class="hljs-literal">True</span>)
</code></div></pre>
留言