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