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

__author__ = 'Evan'


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

__author__ = 'Evan'


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

__author__ = 'Evan'


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地址都是一樣的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章