热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Python3简单使用xmlrpc实现RPC

目录RPCxmlrpc库简单的服务器端简单的客户端多线程访问文件上传&下载RPC先说说什么是RPC,RPC(RemoteProcedureCall&#x

目录

  • RPC
  • xmlrpc库
  • 简单的服务器端
  • 简单的客户端
  • 多线程访问
  • 文件上传&下载

RPC

先说说什么是RPC,RPC(Remote Procedure Call)——远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。

说白了,就是一种远程调用函数接口的方式,客户端和服务端之间约定一种契约(函数接口),然后服务端一直等待客户端的调用。有点像平常的WEB网络请求,不过这种方式非常轻量,不涉及HTTP这些东西,待会可以看到实现很简单。

上面说了,一种用途是在多台服务器之间互相进行调用,另一个用途则在于,不同编程语言之间都支持这种方式,像Python更是内置对其的支持,不需要额外安装什么库,所以可以直接在多语言的服务器之间互相进行调用,很简单。

xmlrpc库

在Python2(网上大部分是Python2使用RPC的资料)中,服务端需要用到SimpleXMLRPCServer库,客户端需要用到ServerProxy库,而在Python3中,两者被整合到了同一个xmlrpc库中,分为xmlrpc.server和xmlrpc.client两部分。所以如果在Python3下使用,就需要导入这个库了。

简单的服务器端

服务器端需要做什么呢?

像web请求一样,我们需要确定供客户端访问的url和端口号,以及供客户端调用的方法实现,最后要让我们服务器一直处于等待被访问的状态:


# _*_ coding:utf-8 _*_from xmlrpc.server import SimpleXMLRPCServer# 调用函数
def respon_string(str):return "get string:%s"%strif __name__ == '__main__':server = SimpleXMLRPCServer(('localhost', 8888)) # 初始化server.register_function(respon_string, "get_string") # 注册函数print ("Listening for Client")server.serve_forever() # 保持等待调用状态

可以看到,代码中就实现了上面说的几点。register_function用于注册一个供调用的函数,第一个参数为自己实现的方法名,第二个参数为供客户端调用的方法名。

简单的客户端

客户端要做的就更少了:根据url和端口号初始化一个服务器对象,然后调用需要的方法即可:

# _*_ coding:utf-8 _*_from xmlrpc.client import ServerProxyif __name__ == '__main__':server = ServerProxy("http://localhost:8888") # 初始化服务器print (server.get_string("cloudox")) # 调用函数并传参

这时候我们用两个终端来跑服务端和客户端,就可以看到效果了:



服务端启动并保持监听


客户端远程调用了多次

从图中可以看到,服务器每次被访问都会打印出访问来源。而客户端访问后,会远程调用在服务端运行的函数具体实现。

多线程访问

上面的方法只能供单线程访问,但大多数情况下都需要支持多线程,该怎么处理呢?很简单,只需要更改一下服务端即可:

# _*_ coding:utf-8 _*_from xmlrpc.server import SimpleXMLRPCServer
from socketserver import ThreadingMixInclass ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):pass# 调用函数1
def respon_string(str):return "get string:%s"%str# 调用函数2
def add(x, y):return x + yif __name__ == '__main__':server = ThreadXMLRPCServer(('localhost', 8888)) # 初始化server.register_function(respon_string, "get_string") # 注册函数1server.register_function(add, 'add') # 注册函数2print ("Listening for Client")server.serve_forever() # 保持等待调用状态

代码中我们初始化服务器用的不再是SimpleXMLRPCServer了,而是自定义的一个类,继承自两个基类,ThreadingMixIn使其能够支持多线程,其余的操作方式还是和普通的一样。并且我们新增了一个函数,接受两个参数,计算和,可以看到无论参数数量多少,我们注册函数的时候都只写函数名。

客户端代码如下:

# _*_ coding:utf-8 _*_from xmlrpc.client import ServerProxyif __name__ == '__main__':server = ServerProxy("http://localhost:8888") # 初始化服务器print (server.get_string("cloudox")) # 调用函数1并传参print (server.add(8, 8)) # 调用函数2并传参

客户端调用两个函数的结果

多线程的效果这里没法展示,不过两个函数的调用都成功了。

文件上传&下载

RPC除了传参以外还可以在客户端与服务器之间传输文件——客户端既可以从服务器下载文件,也可以上传文件到服务器。

传输文件要用到xmlrpc.client.Binary这个库,如果要实现从服务器下载文件的功能,那么服务器端也需要导入这个库,即使它名义上属于client库。

传输文件的基本步骤是:

  • 用open打开一个文件(没有的话会创建),确定是读权限还是写权限;
  • 在文件发送端通过调用xmlrpc.client.Binary来进行文件的传输,接收端通过值.data来获取内容(详见代码);
  • 关闭文件。

服务器:

# _*_ coding:utf-8 _*_from xmlrpc.server import SimpleXMLRPCServer
from socketserver import ThreadingMixIn
import xmlrpc.clientclass ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):pass# 供客户端下载文件
def image_get():handle = open("boy.jpg", 'rb')return xmlrpc.client.Binary(handle.read())# 供客户端上传文件
def image_put(data):handle = open("get_girl.jpg", 'wb')handle.write(data.data)handle.close()if __name__ == '__main__':server = ThreadXMLRPCServer(('localhost', 8888), allow_none=True) # 初始化server.register_function(image_put, 'image_put')server.register_function(image_get, 'image_get')print ("Listening for Client")server.serve_forever() # 保持等待调用状态

代码中初始化服务器时多了个参数allow_none=True,这是允许不返回参数给客户端,因为文件上传的函数都是没有返回值的,不设置这个参数会报错,实际上这里也应该返回一个值告诉客户端是否上传成功。

文件上传的代码中可以看到,写入的是data.data,单单data是会报错的,因为实际上要写入的是Binary.data,这在下面的客户端代码下载文件时也会看到。

客户端:

from xmlrpc.client import ServerProxy
import xmlrpc.clientif __name__ == '__main__':server = ServerProxy("http://localhost:8888", allow_none=True)# 上传文件put_handle = open("girl.jpg", 'rb')server.image_put(xmlrpc.client.Binary(put_handle.read()))put_handle.close()# 下载文件get_handle = open("get_boy.jpg", 'wb')get_handle.write(server.image_get().data)get_handle.close()

可以看到,下载文件时写入的也是获取到的返回值.data,而不是返回值本身,这个一定要注意。

可以查看一下代码目录,会发现文件传输(上传&下载都在一个目录下)成功了:

文件传输结果
注:原始情况下,只有 boy.jpg 和 girl.jpg 两个文件。

以上,就是Python3使用xmlrpc的方式了,可以看到,确实很简单的可以实现远程调用,虽然这里都在一台机器上,不过要支持远程只需要改变IP就可以了。这比搭建一个WEB后台服务器要简单多了,如果只是要实现简单的函数调用,用RPC会节省不少功夫。

这里是我的代码:https://github.com/Cloudox/PythonRPCStudy



推荐阅读
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
author-avatar
buddha覀mito_438
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有