WPF使用xmlrpc实现远程过程调用
这两天刚好有一个需求需要在WPF
中调用Python
编写的算法功能。之前都是使用gRPC
和thrift
框架进行远程过程调用。这次的需求和过程都比较简单,因此想直接尝试下使用Python
提供的SimpleXMLRPCServer
直接包装下已有函数,获得了一个新的技能,也觉得挺好用的,因此把这个项目也整理到Simple WPF
这个系列当中。
如果觉得本博文或者Simple-WPF这个项目有用,请为它点亮一颗小星星。
本次实验的依赖环境如下
WPF:使用Kveer.XmlRPC
这个包来实现远程过程调用客户端
Python: 依赖于Python
自带的标准库中的SimpleXMLRPCServer
实验中将演示如何进行最简单的XmlRpc
调用,以结构体作为函数返回值和数组的传递。
我们先介绍Kveer.XmlRPC
,这是一个基于CookComputing.XmlRpc
并支持.net 2.0
标准的XmlRpc
函数库。因此他的整个命名空间还是沿用的CookComputing.XmlRpc
。
废话不多说,直接上代码,继承XmlRpcClientProtocol
并实现对应的Rpc
方法,在类定义上增加注解指定调用的端口和URL即可。
需要提一下的是,XmlRpcStruct
可以看作一个字典,对于XmlRpcStruct
类型我们也只需要声明一个类并对对应的成员加上对应注解来映射对象即可。
using CookComputing.XmlRpc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SimpleXMLRpcDemo
{
internal class Structure
{
[XmlRpcMember("name")]
public string Name { get; set; }
[XmlRpcMember("age")]
public int Age { get; set; }
[XmlRpcMember("gender")]
public string Gender { get; set; }
}
[XmlRpcUrl("http://127.0.0.1:8000/rpc")]
internal class RpcWorker : XmlRpcClientProtocol
{
[XmlRpcMethod]
public string Foo()
{
return (string)Invoke("Foo", new object[] { });
}
[XmlRpcMethod]
public Structure BarWithStructureInvoke()
{
return (Structure)Invoke("BarWithStructureInvoke", new object[] { });
}
[XmlRpcMethod]
public double SumArray(double[] array)
{
return (double)Invoke("SumArray", new object[] { array });
}
}
}
有了客户端调用的代码,我们来到Python
环境来编写远程过程调用的实现。在这里我们也使用一个工作类来管理和注册所有用到的函数。值得一提的是,我们可以通过继承SimpleXMLRPCRequestHandler
并指定rpc_paths
的方法来自定义调用的URL
地址.
from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
import logging
import numpy as np
logging.basicConfig(level=logging.INFO)
class RequestHandler(SimpleXMLRPCRequestHandler):
rpc_paths = ('/rpc',)
class Funcs:
def __init__(self) -> None:
# do nothing in this function
pass
def Foo(self):
return 'bar'
def BarWithStructureInvoke(self):
return {'name': 'Bob', 'age': 10, 'gender': 'male'}
def SumArray(self, a:[]):
a = np.array(a)
sum = np.sum(a)
return float(sum)
server = SimpleXMLRPCServer(('127.0.0.1', 8000), logRequests=True, requestHandler=RequestHandler)
server.register_instance(Funcs())
server.serve_forever()
在完成上述编码工作后,先启动Python
的远程过程调用服务,再启动刚刚编写的WPF程序应该就可以看到下图的效果啦
踩坑
- 这个远程过程调用怎么那么慢????
可以检查一下是不是写了localhost
作为服务器客户端调用地址,localhost
是一个特殊的主机名也需要DNS
解析,因此有可能是DNS
慢。
博主实测,使用localhost
,每2秒调用一次。使用127.0.0.1
,每秒调用可以达到1000次。 - 为什么不能传
float
????
实测只能接受string
,int
,double
,XmlRpcStruct
,以及以上基本类型的数组。其他数据类型需要自行实现序列化和反序列化支持。
参考文章
感谢扫码支持