Python实现简易RPC框架:基于Socket与JSON的完整示例

陈默
陈默
发布时间:2026-10-14| 6人浏览过
原创

本文介绍如何使用Python Socket API和JSON序列化实现一个简易的RPC框架。通过继承机制封装TCPClient和RPCStub,客户端动态生成代理方法并序列化请求,服务端接收并反序列化执行对应函数。代码展示了从连接、注册方法到通信的完整流程,适合理解RPC基本原理。

Python实现简易RPC框架:基于Socket与JSON的完整示例

阅读本文前,建议具备基础的Python Socket网络编程知识。

回顾RPC基本概念

回顾RPC基本概念

  • 客户端(Client):发起服务调用的主体。
  • 客户端存根(Client Stub):负责存储服务端地址,将客户端调用的参数打包为网络消息,并通过网络传输发送至服务端。
  • 服务端存根(Server Stub):接收客户端发送的消息,进行解包处理,随后调用本地实际服务逻辑进行处理。
  • 服务端(Server):真正提供服务逻辑的组件。
  • Network Service:底层传输层,支持TCP或HTTP协议。

实现JSON-RPC协议

实现JSON-RPC协议

整体设计思路

在编写代码前,先梳理整体设计思路。

1、Network Service部分直接利用Python Socket相关API实现;2、数据传输格式采用JSON,在Socket层会自动转换为二进制流,开发者无需手动处理二进制编码细节。

参考xmlrpc的设计模式,Client与Server均采用Mixin多继承机制构建,每个类职责单一,最终对外暴露的仅是一个封装后的类及其有限的方法接口。

Client端实现细节

首先从Client端代码开始实现。


# client.py

 

import rpcclient

 

c = rpcclient.RPCClient()

c.connect('127.0.0.1', 5000)

res = c.add(1, 2, c=3)

print(f'res: [{res}]')

使用示例为:实例化rpcclient.RPCClient类,调用connect方法连接Server端,随后直接调用Server端的add方法。该方法逻辑为将传入参数累加并返回结果,最后打印add方法的返回值。

RPCClient类同时继承自TCPClient类与RPCStub类。


# rpclient.py

class RPCClient(TCPClient, RPCStub):

    pass

其中TCPClient负责通过Socket建立TCP连接并发送数据请求,而RPCStub类主要负责将Client端调用Server端方法的相关信息打包,随后调用TCPClient类中的发送方法即可。这两个类的具体实现在rpclient.py文件中,代码如下。


class TCPClient(object):

    def __init__(self):

        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

 

    def connect(self, host, port):

        '''链接Server端'''

        self.sock.connect((host, port))

 

    def send(self, data):

        '''将数据发送到Server端'''

        self.sock.send(data)

 

    def recv(self, length):

        '''接受Server端回传的数据'''

        return self.sock.recv(length)

         

 

class RPCStub(object):

    def __getattr__(self, function):

        def _func(*args, **kwargs):

            d = {'method_name': function, 'method_args': args, 'method_kwargs': kwargs}

            self.send(json.dumps(d).encode('utf-8')) # 发送数据

            data = self.recv(1024) # 接收方法执行后返回的结果

            return data

 

        setattr(self, function, _func)

        return _func

TCPClient类仅涉及常规的Socket API操作,此处不再赘述,重点分析RPCStub类的实现。

当在Client端执行res = c.add(1, 2, c=3)时,实际触发RPCStub中的__getattr__方法。该方法提取Client端调用的方法名及参数,通过TCPServer类的send方法发送数据。发送前对数据进行JSON格式化,以便Server端解码,随后调用recv方法等待Server端返回的执行结果。

由于RPCClient类本身并未定义add方法,为实现用户直接在Client端调用Server端方法的体验,代码利用__getattr__动态构建_func方法,并通过setattr方法将其绑定到RPCClient类实例中。此时,该类便拥有了Server端方法的映射能力。

调用add方法时,实际执行对应的_func方法,将构造好的数据发送至Server端。

Server端实现与测试

Client端逻辑至此完成,接下来实现Server端,过程同样简洁。

Server端的使用方式如下。


# server.py

 

import rpcserver

 

def add(a, b, c=10):

    sum = a + b + c

    return sum

 

s = rpcserver.RPCServer()

s.register_function(add) # 注册方法

s.loop(5000) # 传入要监听的端口

实例化rpcserver.RPCServer类,通过register_function方法注册希望被Client端调用的函数,随后调用loop方法并传入监听端口。RPCServer类的具体实现如下。


# rpcserver.py

 

class RPCServer(TCPServer, JSONRPC, RPCStub):

    def __init__(self):

        TCPServer.__init__(self)

        JSONRPC.__init__(self)

        RPCStub.__init__(self)

 

    def loop(self, port):

        # 循环监听 5000 端口

        self.bind_listen(port)

        print('Server listen 5000 ...')

        while True:

            self.accept_receive_close()

 

    def on_msg(self, data):

        return self.call_method(data)

RPCServer类继承自TCPServer、JSONRPC及RPCStub,这些类的具体实现在rpcserver.py文件中,且代码已包含详细注释,故此处不再展开解释。


class TCPServer(object):

    def __init__(self):

        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

 

    def bind_listen(self, port):

        self.sock.bind(('0.0.0.0', port))

        self.sock.listen(5)

 

    def accept_receive_close(self):

        '''获取Client端信息'''

        (client_socket, address) = self.sock.accept()

        msg = client_socket.recv(1024)

        data = self.on_msg(msg)

        client_socket.sendall(data) # 回传

        client_socket.close()

 

 

class JSONRPC(object):

    def __init__(self):

        self.data = None

 

    def from_data(self, data):

        '''解析数据'''

        self.data = json.loads(data.decode('utf-8'))

 

    def call_method(self, data):

        '''解析数据,调用对应的方法变将该方法执行结果返回'''

        self.from_data(data)

        method_name = self.data['method_name']

        method_args = self.data['method_args']

        method_kwargs = self.data['method_kwargs']

        res = self.funs[method_name](*method_args, **method_kwargs)

        data = {"res": res}

        return json.dumps(data).encode('utf-8')

 

 

class RPCStub(object):

    def __init__(self):

        self.funs = {}

 

    def register_function(self, function, name=None):

        '''Server端方法注册,Client端只可调用被注册的方法'''

        if name is None:

            name = function.__name__

        self.funs[name] = function

至此,Client端与Server端的代码均编写完毕。

测试环节:

以上即为Python实现简单RPC框架的示例详解,更多关于Python实现RPC框架的资料,请关注本站其他相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。