【C++】RPC:远程程序调用

1、简述

RPC:Remote Procedure Call,远程程序调用,像调用本地函数一样调用远程服务器上的方法,和HTTP请求类似,但是每个功能分的较细,同时也规定了参数格式。

常见的RPC如下:

特性 XML-RPC SOAP REST JSON-RPC gRPC
基础协议 HTTP + XML HTTP + XML HTTP HTTP + JSON HTTP/2 + Protobuf
复杂度 中高
消息体积 更大 极小
性能 一般 较差 良好 良好 优秀
数据类型 有限 丰富 灵活 简单 强大
安全性 依赖 HTTP 内置 WS-Security 需额外实现 依赖 HTTP 内置 TLS
适用场景 简单跨平台 RPC 企业级复杂服务 Web API 轻量级 RPC 高性能微服务

2、XML-RPC

XML-RPC 是一种基于 XML 编码和HTTP 传输的远程过程调用协议。

本质是一种分布式计算协议,它将远程函数调用封装为 HTTP POST 请求,使用 XML 格式描述调用的方法名和参数,服务器执行后将结果以 XML 格式返回给客户端。

2.1 工作原理

XML-RPC 的通信流程遵循典型的请求 - 响应模式,步骤如下

  • 客户端请求:构造 XML 格式的 RPC 请求,包含方法名和参数,通过 HTTP POST 发送到服务器特定端点
  • 服务器接收: 解析 HTTP 请求头,提取 XML payload
  • XML 解析:解析 XML 文档,识别目标方法和参数值
  • 方法执行: 在服务器端调用对应的方法,传入解析后的参数
  • 结果封装: 将执行结果(成功返回值或错误信息)编码为 XML 格式
  • 响应返回: 通过 HTTP 响应将 XML 结果返回给客户端
  • 客户端处理: 解析响应 XML,提取结果并进行后续处理

2.2 HTTP 传输层要求

必须使用HTTP POST方法,不支持 GET

请求头必须包含:

  • Content-Type: text/xml
  • Content-Length: 正确的请求体长度
  • User-Agent 和 Host 字段
  • 标准端点路径:通常为 /RPC2,但可自定义

2.3 XML 消息结构

1)请求消息(methodCall)

xml 复制代码
<?xml version="1.0"?>
<methodCall>
	<methodName>calculator.add</methodName>  <!-- 必选:方法名,支持命名空间 -->
	<params>                                 <!-- 可选:参数列表 -->
		<param><value><i4>5</i4></value></param>  <!-- 参数1:整数5 -->
		<param><value><double>3.2</double></value></param>  <!-- 参数2:浮点数3.2 -->
	</params>
</methodCall>

2)成功响应:

xml 复制代码
<?xml version="1.0"?>
<methodResponse>
  <params>
    <param><value><double>8.2</double></value></param>  <!-- 返回结果:8.2 -->
  </params>
</methodResponse>

3)错误响应:

xml 复制代码
<?xml version="1.0"?>
<methodResponse>
  <fault>
    <value>
      <struct>
        <member>
          <name>faultCode</name>
          <value><i4>4</i4></value>  <!-- 错误代码 -->
        </member>
        <member>
          <name>faultString</name>
          <value><string>Invalid parameters</string></value>  <!-- 错误描述 -->
        </member>
      </struct>
    </value>
  </fault>
</methodResponse>

2.4 数据类型

XML-RPC 定义了11 种标准数据类型

  • 整数 <i4> 或 <int> 32 位有符号整数
  • 布尔值 <boolean> 0(假)或 1(真)
  • 字符串 <string> 文本字符串(可省略标签)
  • 双精度浮点数 <double> 64 位浮点数
  • 日期时间 <dateTime.iso8601> ISO 8601 格式日期时间
  • 二进制数据 <base64> Base64 编码的二进制数据
  • 数组 <array> 有序值列表,包含在<data>标签中
  • 结构体 <struct> 键值对集合,包含多个<member>
  • 64 位整数 <i8> 非标准扩展,不同实现可能有差异
  • 空值 <nil> 非标准扩展,用于表示空值
  • 长字符串 <string> 无长度限制,通过 XML 自然支持

1)数组示例

xml 复制代码
<value>
  <array>
    <data>
      <value><string>apple</string></value>
      <value><string>banana</string></value>
      <value><i4>10</i4></value>
    </data>
  </array>
</value>

2)结构体示例

xml 复制代码
<value>
  <struct>
    <member>
      <name>name</name>
      <value><string>John Doe</string></value>
    </member>
    <member>
      <name>age</name>
      <value><i4>30</i4></value>
    </member>
  </struct>
</value>

2.5 C++库 libxmlrpc

源码下载:

复制代码
https://xmlrpc-c.sourceforge.io/

命令安装:

C库

复制代码
sudo apt install libxmlrpc-core-c3 libxmlrpc-core-c3-dev

C++封装

复制代码
sudo apt install libxmlrpc-c++8v5 libxmlrpc-c++8-dev

命令行工具

复制代码
sudo apt install xmlrpc-api-utils

示例下载:

复制代码
https://sourceforge.net/p/xmlrpc-c/code/HEAD/tree/trunk/

3、JSON-RPC

JSON-RPC 和 XML-RPC 比较相似,都是通过HTTP传输,消息体一个为JSON,另一个为XML

3.1 和XML-RPC相比

1)优缺点总结

XML-RPC

  • 优点:早年跨平台通用、规范统一、老旧系统全覆盖
  • 缺点:笨重、慢、冗余高、开发繁琐、现代项目基本淘汰

JSON-RPC

  • 优点:轻量、高速、易调试、前端友好、生态成熟、适配微服务
  • 缺点:无原生日期 / 二进制专用类型,老古董系统不兼容

3.2 C++库:jsonrpccpp

3.2.1 安装

复制代码
sudo apt install libjsonrpccpp-dev libjsonrpccpp-tools

3.2.2 使用

1)服务端:server.cpp

cpp 复制代码
#include <iostream>
#include <jsonrpccpp/server.h>
#include <jsonrpccpp/server/connectors/httpserver.h>

using namespace jsonrpc;
using namespace std;

class MyServer : public AbstractServer<MyServer>
{
public:
    MyServer(AbstractServerConnector &connector) : AbstractServer<MyServer>(connector)
    {
        bindAndAddMethod(Procedure("add", PARAMS_BY_POSITION, JSON_INTEGER, "a", JSON_INTEGER, "b", JSON_INTEGER, NULL), &MyServer::add);
        bindAndAddMethod(Procedure("sayHello", PARAMS_BY_POSITION, JSON_STRING, "name", JSON_STRING, NULL), &MyServer::sayHello);
    }

    void add(const Json::Value& params, Json::Value& result)
    {result = params[0].asInt() + params[1].asInt();}

    void sayHello(const Json::Value& params, Json::Value& result)
    {result = "Hello, " + params[0].asString() + "!";}
};

int main()
{
    HttpServer server(8080);
    MyServer serv(server);

    cout << "服务端运行在 8080 端口" << endl;
    serv.StartListening();
    getchar();
    serv.StopListening();
    return 0;
}

2)客户端:client.cpp

cpp 复制代码
#include <iostream>
#include <jsonrpccpp/client.h>
#include <jsonrpccpp/client/connectors/httpclient.h>

using namespace jsonrpc;
using namespace std;

int main()
{
    try{
        HttpClient httpClient("http://localhost:8080");
        Client rpc(httpClient, JSONRPC_CLIENT_V2);

        Json::Value params_add;
        params_add.append(10);    // 构造 JSON 数组 [10, 20]
        params_add.append(20);
        Json::Value sum = rpc.CallMethod("add", params_add);

        Json::Value params_hello;
        params_hello.append("Ubuntu 22.04"); // 构造 JSON 数组 ["Ubuntu 22.04"]
        Json::Value greet = rpc.CallMethod("sayHello", params_hello);

        cout << "add(10, 20) = " << sum.asInt() << endl;
        cout << greet.asString() << endl;
    }catch (JsonRpcException& e){
        cerr << "错误: " << e.what() << endl;
    }
    return 0;
}

3.2.3 编译、测试

复制代码
g++ -std=c++11 server.cpp -o server -ljsonrpccpp-server -ljsonrpccpp-common -ljsoncpp
g++ -std=c++11 client.cpp -o client -ljsonrpccpp-client -ljsonrpccpp-common -ljsoncpp

3.3.4 卸载

复制代码
sudo apt remove  libjsonrpccpp-dev libjsonrpccpp-client0 libjsonrpccpp-common0 \
	libjsonrpccpp-server0 libjsonrpccpp-tools

3.4 C++库:json-rpc-cxx

Jsonrpccpp 版本比较旧,有各种问题,建议使用 json-rpc-cxx

下载地址:

复制代码
https://github.com/jsonrpcx/json-rpc-cxx

安装依赖:

复制代码
sudo apt install nlohmann-json3-dev

json-rpc-cxx 依赖第三方库:

复制代码
cpp-httplib  doctest  nlohmann
相关推荐
承渊政道1 小时前
【贪心算法】(经典实战应用解析(六):整数替换、俄罗斯套娃信封问题、可被三整除的最⼤和、距离相等的条形码、重构字符串)
c++·算法·leetcode·贪心算法·排序算法·动态规划·哈希算法
宠..1 小时前
VS Code SSH 远程连接 Ubuntu 并实现快速运行(C/C++示例)
java·运维·c语言·开发语言·c++·ubuntu·ssh
闻缺陷则喜何志丹1 小时前
【图论 树 启发式合并】P7165 [COCI2020-2021#1] Papričice|普及+
c++·算法·启发式算法·图论··洛谷
alexwang2111 小时前
AT_abc458_d [ABC458D] Chalkboard Median题解
c++·算法·题解·atcoder
故事和你911 小时前
洛谷-【图论2-4】连通性问题1
开发语言·数据结构·c++·算法·动态规划·图论
我先去打把游戏先1 小时前
Ubuntu虚拟机(服务器版本)Git安装教程(附常用命令)——从零开始掌握版本控制
服务器·c语言·c++·git·嵌入式硬件·物联网·ubuntu
艾莉丝努力练剑1 小时前
【Linux网络】Linux 网络编程:HTTP(四)从手写服务器到生产级 Nginx 与 cpp-httplib 实战
linux·运维·服务器·网络·c++·nginx·http
咩咦1 小时前
C++学习笔记21:日期类加减天数
c++·学习笔记·运算符重载·日期类·operator+·operator+=
努力努力再努力wz1 小时前
【QT入门系列】QWidget 六大常用属性详解:windowOpacity、cursor、font、focus、toolTip 与 styleSheet
android·开发语言·数据结构·c++·qt·mysql·算法