有勇气的牛排博客

python标准库xmlrpc 之RPC远程方法调用

有勇气的牛排 638 Python 2023-01-08 14:41:25

💖💖💖养成每日阅读好习惯, 每天进步, 超越昨天的自己💖💖💖
愿景:输出体系化编程知识与技巧,助力软件行业发展与从业者学习减负,让编程产生更大价值。

🔎🔎🔎
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__': # 多线程 class ThreadXMLRPCServer server = ThreadXMLRPCServer((rpc_server, rpc_port)) print("Listening on port 8000...") # 注册函数 server.register_function(get_name, "get_name") # 保持等待调用状态 server.serve_forever()

(2)client

# _*_ coding:utf-8 _*_ 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}/") # 调用函数 get_name 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 # DateTime 对象 def get_server_time(): today = datetime.today() return xmlrpc.client.DateTime(today) if __name__ == '__main__': # 多线程 class ThreadXMLRPCServer 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)

image.png

四、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__': # 多线程 class ThreadXMLRPCServer server = ThreadXMLRPCServer((rpc_server, rpc_port), allow_none=True) # server = SimpleXMLRPCServer((rpc_server, rpc_port)) 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() # 下载文件 # get_handle = open("./tmp/test.txt", 'wb') # get_handle.write(server.get_file().data) # get_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)

留言

专栏
文章
加入群聊