• Python(00):Python网络编程:xmlrpc模块xmlrcplib


    简介

    rpc:远程过程调用协议。简单的来说就是客户端可以很方便得远程调用服务端的接口程序,而不用管底层是如何实现的。

    XML-RPC的全称是XML Remote Procedure Call,即XML(标准通用标记语言下的一个子集)远程过程调用。它是一套允许运行在不同操作系统、不同环境的程序实现基于Internet过程调用的规范和一系列的实现。这种远程过程调用使用http作为传输协议,XML作为传送信息的编码格式。Xml-Rpc的定义尽可能的保持了简单,但同时能够传送、处理、返回复杂的数据结构。这个过程也被大家称为“分布式计算”。
    xmlrpc:使用http协议作为传输协议的rpc机制。
    rpc框架图

    1、注册函数:register_function

    以下是定义了一个函数的xmlrpc服务端。

    register_function用于注册一个供调用的函数,第一个参数为自己实现的方法名,第二个参数为供客户端调用的方法名。

    from xmlrpc.server import SimpleXMLRPCServer  #导入模块
    s = SimpleXMLRPCServer(("10.55.22.11",4242))  #服务端ip假设为10.55.22.11,端口假设为4242
    def twice(x):                                 #定义函数
        return x*2
    s.register_function(twice)                    #注册函数(让客户端发现)
    s.serve_forever()                             #启动服务端

    下面是该服务端对应的xmlrpc客户端

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

    import xmlrpc.client    #导入模块
    s = xmlrpc.client.ServerProxy('http://10.55.22.11:4242')  #链接服务端
    print(s.twice(2))   #调用函数

    调用成功成功后服务端会显示
    在这里插入图片描述

    2、注册类方法函数:register_instance

     服务端如:

    from xmlrpc.server import SimpleXMLRPCServer  # 导入模块
    s = SimpleXMLRPCServer(("10.81.10.57",4242))  # 设置服务端ip和端口    
    class Animal:                   #定义类
        def rabit(self, amount):
            return 4*amount
        def chicken(self, amount):
            return 2*amount
    s.register_instance(Animal())                 # 注册类方法函数(让客户端发现)
    s.serve_forever()                             # 启动服务端

    对应的客户端如下:

    import xmlrpc.client    # 导入模块
    s = xmlrpc.client.ServerProxy('http://10.81.10.57:4242')  # 链接服务端
    print(s.rabit(2))   # 调用函数
    print(s.chicken(2))

    3、dispatch方法

    接下来要修改一些注册类方法函数接口的参数,对应的修改一下类定义。通过在类定义中添加—_dispatch方法可以在远程调用接口的时候经过_dispach。
    服务端如下:

    from xmlrpc.server import SimpleXMLRPCServer     # 导入模块
    s = SimpleXMLRPCServer(("10.81.10.57",4242))     # 设置服务端ip和端口
    class Animal:                                    # 定义类
        def _dispatch(self, method, param):          # 定义_dispatch方法
            print(method)                            # 在服务端显示调用的方法名
            func = getattr(self, method)             # 调用接口
            return func(*param)   
        def rabit(self, amount):
            return 4*amount
        def chicken(self, amount):
            return 2*amount    
    s.register_instance(Animal())                    # 注册函数(让客户端发现)
    s.serve_forever()                                # 启动服务端

    客户端如下:

    import xmlrpc.client    # 导入模块
    s = xmlrpc.client.ServerProxy('http://10.81.10.57:4242')  # 链接服务端
    print(s.rabit(2))   # 调用函数
    print(s.chicken(2))

    注: 服务器端运行结果:

    在这里插入图片描述

    4、多线程访问

    初始化服务器用的不再是SimpleXMLRPCServer了,而是自定义的一个类,继承自两个基类,ThreadingMixIn使其能够支持多线程,其余的操作方式还是和普通的一样。

    并且我们新增了一个函数,接受两个参数,计算和,可以看到无论参数数量多少,我们注册函数的时候都只写函数名

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

    客户端代码如下:

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

    5、文件上传&下载

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

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

    传输文件的基本步骤是:

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

    服务器:

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

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

    from xmlrpc.server import SimpleXMLRPCServer
    from socketserver import ThreadingMixIn
    import xmlrpc.client
    
    
    class 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() # 保持等待调用状态

    客户端

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

    from xmlrpc.client import ServerProxy
    import xmlrpc.client
    
    if __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()
  • 相关阅读:
    根据group by、count case when 分组分类统计
    Cron表达式
    SQL分页查询 — 不同页面的查询结果有重复数据
    Dockerfile文件语法
    redis获取系统当前时间
    mybatis oracle批量插入数据
    Mysql函数->TRIM(去掉首尾空格、任意字符)
    Oracle函数->TRIM(去掉首尾空格、首尾字符)
    使用redis-list类型 限制用户1分钟内访问次数为100次
    一文了解mysql基础架构
  • 原文地址:https://www.cnblogs.com/springsnow/p/12121187.html
Copyright © 2020-2023  润新知