Python3使用xmlrpc库简单实现RPC功能

一、RPC简介

1. RPC

RPC (Remote Procedure Call) 即远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC在通信中可以为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层,是分布式系统中常见的一种通信方法。

RPC采用客户端/服务器模式。请求程序就是一个客户端,而提供服务的程序就是一个服务器。首先,客户端调用进程发送一个请求信息到服务器端,然后等待应答信息。在服务器端,进程保持睡眠状态直到请求信息到达为止。当一个请求信息到达,服务器获得进程参数,然后执行对应的服务方法并返回结果给客户端,随后继续等待下一个请求信息,直到关闭服务器端进程为止。

2. xmlrpc库

在Python2中服务器端需要用到SimpleXMLRPCServer库,客户端需要用到ServerProxy库,而在Python3中,两者被整合到了同一个xmlrpc库中,分别是xmlrpc.serverxmlrpc.client

二、简单使用

1. 服务器端的实现

因为是从网络访问,所以和web请求一样,我们需要确定供客户端访问的URL端口号,以及供客户端调用的服务方法,最后还要让我们的服务器一直处于可以被访问的状态

Example:

from xmlrpc.server import SimpleXMLRPCServer

def setup_socket_server(ip_address='localhost', port=6666):
	"""
    注册一个函数或者类来响应XML-RPC请求,并启动XML-RPC服务器
    :param ip_address: 供客户端连接的IP地址,默认使用localhost,localhost为当前网卡IP,也可以自己指定合法有效的IP地址
    :param port: 供客户端连接的端口号,默认为6666
    :return:
    """
    try:
        service = SimpleXMLRPCServer((ip_address, port))  # 初始化XML-RPC服务
        # 注册一个函数来响应XML-RPC请求,客户端只能调用已注册的函数,比较单一
        service.register_function(function)
        # 注册一个类来响应XML-RPC请求,使用类的好处就是可以把多个方法写到一起,方便管理和调用
        service.register_instance(ServiceMethod())
        service.serve_forever()  # 启动服务器并永久运行
    except Exception as ex:
        raise Exception('Setup socket server error:\n{}'.format(ex))

上面这段代码描述了一个简单的服务器端实现过程,下面开始展示完整的服务器端配置过程
代码如下:

# -*- coding:utf-8 -*-
import os
import re
from xmlrpc.server import SimpleXMLRPCServer


class ServiceMethod(object):
    """
    这个类包含客户端所有能被执行的方法
    每个方法必须要有一个返回值,如果没有合适的返回值可以直接返回True
    """
    @staticmethod
    def get_server_ip():
        """
        获取服务器端的IP地址
        :return:
        """
        result = os.popen('ipconfig')
        ip_address = re.search(r'IPv4.+?: (\d+?\.\d+?\.\d+?\.\d+)', result .read())
        if ip_address:
            return ip_address.group(1)
        else:
            return 'Server ip address was not found'


def get_server_host_name():
    """
    这是获取服务器端计算机主机名的函数
    :return:
    """
    result = os.popen('ipconfig /all')
    host_name = re.search(r'主机名.+?: (\w+)', result.read())
    if host_name:
        return host_name.group(1)
    else:
        return 'Server host name was not found'


def setup_socket_server(ip_address='localhost', port=6666):
    """
    注册一个函数或者类来响应XML-RPC请求,并启动XML-RPC服务器
    :param ip_address: 供客户端连接的IP地址,默认使用localhost,localhost为当前网卡IP,也可以自己指定合法有效的IP地址
    :param port: 供客户端连接的端口号,默认为6666
    :return:
    """
    try:
        service = SimpleXMLRPCServer((ip_address, port))  # 初始化XML-RPC服务
        print('Server {} Listening on port {} ...'.format(ip_address, port))
        service.register_function(get_server_host_name)  # 注册一个函数
        service.register_instance(ServiceMethod())  # 注册一个类
        service.serve_forever()  # 启动服务器并永久运行
    except Exception as ex:
        raise Exception('Setup socket server error:\n{}'.format(ex))


if __name__ == '__main__':
    setup_socket_server(ip_address='172.31.9.156')

执行结果:

Server 172.31.9.156 Listening on port 6666 ...

我这里用的是本机自动分配的IP地址,像这样一个服务器端就启动好了,这个Python进程在执行后就不会关闭了,这里有注册两个可调用的方法get_server_host_nameServiceMethod(),接下来看客户端的实现。

2. 客户端的实现

客户端需要配置服务器端的IP地址端口号初始化一个服务器对象,然后调用对应的服务器端方法即可。
代码如下:

# -*- coding:utf-8 -*-
from xmlrpc.client import ServerProxy


def setup_socket_client(ip_address, port=6666):
    proxy = ServerProxy('http://%s:%s/' % (ip_address, port), allow_none=True)
    print('Connect to {}:{} successful ...'.format(ip_address, port))

    host_name = proxy.get_server_host_name()
    print('Received the server host name: {}'.format(host_name))

    server_ip = proxy.get_server_ip()
    print('Received the server ip: {}'.format(server_ip))


if __name__ == '__main__':
    setup_socket_client(ip_address='172.31.9.156')

客户端执行结果:

Connect to 172.31.9.156:6666 successful ...
Received the server host name: EVALIU
Received the server ip: 172.31.9.156

连接服务器端成功,并打印了服务器端函数的返回结果
下面看服务器端响应结果:

Server 172.31.9.156 Listening on port 6666 ...
172.31.9.156 - - [15/Jan/2020 10:05:10] "POST / HTTP/1.1" 200 -
172.31.9.156 - - [15/Jan/2020 10:05:10] "POST / HTTP/1.1" 200 -

可以看到,服务器每次被访问都会打印出访问来源,我这里是本机客户端连接本机服务器端所以IP地址都是一样的。

发布了27 篇原创文章 · 获赞 10 · 访问量 387

猜你喜欢

转载自blog.csdn.net/weixin_43750377/article/details/103978127