JsonRPC 是一种轻量级的远程过程调用(RPC)协议,采用 JSON 作为数据格式。它广泛应用于不同的网络通信场景,如 Web 服务、物联网(IoT)等。Qt/C++ 提供了强大的网络库(如 QTcpSocketQTcpServer)和 JSON 解析库(QJsonDocumentQJsonObject)来支持 JsonRPC 的实现。

本文将详细介绍 Qt/C++ 中如何使用 JsonRPC,包括 JSON 数据格式、JsonRPC 协议、Qt 中的 JSON 处理方法,并通过具体示例演示客户端和服务器如何通信。


一、Json 数据格式

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,主要特性包括:

  • 易于人阅读和编写
  • 独立于编程语言
  • 适用于数据传输
JSON 结构

JSON 支持的主要数据类型:

  • 对象(Object):使用 {} 定义,包含多个 key:value 键值对。
  • 数组(Array):使用 [] 定义,包含多个值。
  • 字符串(String):使用 "" 双引号包围。
  • 数字(Number):支持整数和浮点数。
  • 布尔值(Boolean):truefalse
  • 空值(Null):null
示例:学生信息
{
    "姓名": "XXX",
    "年龄": 20,
    "成绩": [88.5, 99, 58],
    "爱好": {
        "书籍": "西游记",
        "运动": "打篮球"
    }
}

在 Qt/C++ 中,可以使用 QJsonObjectQJsonArray 处理 JSON 数据。


二、Qt/C++中的JSON处理

Qt 提供了 QJsonDocumentQJsonObjectQJsonArray 进行 JSON 解析和生成。

1. 生成 JSON
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>

void createJson() {
    QJsonObject student;
    student["姓名"] = "XXX";
    student["年龄"] = 20;

    QJsonArray scores;
    scores.append(88.5);
    scores.append(99);
    scores.append(58);
    student["成绩"] = scores;

    QJsonObject hobby;
    hobby["书籍"] = "西游记";
    hobby["运动"] = "打篮球";
    student["爱好"] = hobby;

    // 序列化 JSON
    QJsonDocument doc(student);
    qDebug() << doc.toJson();
}

int main() {
    createJson();
    return 0;
}
2. 解析 JSON
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>

void parseJson(const QByteArray &jsonData) {
    QJsonDocument doc = QJsonDocument::fromJson(jsonData);
    if (!doc.isObject()) {
        qDebug() << "Invalid JSON format";
        return;
    }

    QJsonObject student = doc.object();
    qDebug() << "姓名:" << student["姓名"].toString();
    qDebug() << "年龄:" << student["年龄"].toInt();

    QJsonArray scores = student["成绩"].toArray();
    for (const QJsonValue &score : scores) {
        qDebug() << "成绩:" << score.toDouble();
    }
}

int main() {
    QByteArray jsonStr = R"({
        "姓名": "小明",
        "年龄": 18,
        "成绩": [88.5, 99, 58]
    })";
    parseJson(jsonStr);
    return 0;
}

三、JsonRPC协议

JsonRPC 是基于 JSON 的远程过程调用协议。其核心结构包括:

  • 请求
  • 响应
  • 错误信息(可选)
JsonRPC 请求示例
{
    "jsonrpc": "2.0",
    "method": "add",
    "params": [5, 10],
    "id": 1
}
JsonRPC 响应示例
{
    "jsonrpc": "2.0",
    "result": 15,
    "id": 1
}
错误响应示例
{
    "jsonrpc": "2.0",
    "error": {
        "code": -32601,
        "message": "Method not found"
    },
    "id": 1
}

四、Qt/C++ 实现 JsonRPC 服务器

使用 QTcpServerQTcpSocket 实现 JsonRPC 服务器。

JsonRpcServer.h
#ifndef JSONRPCSERVER_H
#define JSONRPCSERVER_H

#include <QTcpServer>
#include <QTcpSocket>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

class JsonRpcServer : public QTcpServer
{
    Q_OBJECT

public:
    JsonRpcServer(QObject *parent = nullptr);
    ~JsonRpcServer();

protected:
    void incomingConnection(qintptr socketDescriptor) override;

private slots:
    void onReadyRead();
    void onDisconnected();

private:
    void processRequest(QTcpSocket *clientSocket, const QByteArray &requestData);
};

#endif // JSONRPCSERVER_H
JsonRpcServer.cpp
#include "JsonRpcServer.h"

JsonRpcServer::JsonRpcServer(QObject *parent) : QTcpServer(parent) {}

JsonRpcServer::~JsonRpcServer() {}

void JsonRpcServer::incomingConnection(qintptr socketDescriptor) {
    QTcpSocket *clientSocket = new QTcpSocket(this);
    if (!clientSocket->setSocketDescriptor(socketDescriptor)) {
        delete clientSocket;
        return;
    }
    connect(clientSocket, &QTcpSocket::readyRead, this, &JsonRpcServer::onReadyRead);
    connect(clientSocket, &QTcpSocket::disconnected, this, &JsonRpcServer::onDisconnected);
}

void JsonRpcServer::onReadyRead() {
    QTcpSocket *clientSocket = static_cast<QTcpSocket *>(sender());
    QByteArray requestData = clientSocket->readAll();
    processRequest(clientSocket, requestData);
}

void JsonRpcServer::onDisconnected() {
    QTcpSocket *clientSocket = static_cast<QTcpSocket *>(sender());
    clientSocket->deleteLater();
}

void JsonRpcServer::processRequest(QTcpSocket *clientSocket, const QByteArray &requestData) {
    QJsonDocument doc = QJsonDocument::fromJson(requestData);
    if (!doc.isObject()) return;

    QJsonObject request = doc.object();
    QString method = request["method"].toString();
    int id = request["id"].toInt();

    QJsonObject response;
    response["jsonrpc"] = "2.0";
    response["id"] = id;

    if (method == "add") {
        QJsonArray params = request["params"].toArray();
        int result = params[0].toInt() + params[1].toInt();
        response["result"] = result;
    } else {
        response["error"] = QJsonObject{{"code", -32601}, {"message", "Method not found"}};
    }

    clientSocket->write(QJsonDocument(response).toJson());
}

五、Qt/C++ 实现 JsonRPC 客户端**

客户端使用 QTcpSocket 连接服务器,发送 JSON RPC 请求并解析响应。

JsonRpcClient.h
#ifndef JSONRPCCLIENT_H
#define JSONRPCCLIENT_H

#include <QObject>
#include <QTcpSocket>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

class JsonRpcClient : public QObject
{
    Q_OBJECT

public:
    JsonRpcClient(const QString &host, quint16 port, QObject *parent = nullptr);
    ~JsonRpcClient();

    void sendRequest(const QString &method, const QJsonArray &params, int id);

private slots:
    void onConnected();
    void onReadyRead();
    void onErrorOccurred(QAbstractSocket::SocketError socketError);

private:
    QTcpSocket *socket;
    QString host;
    quint16 port;
    void processResponse(const QByteArray &response);
    QByteArray createJsonRpcRequest(const QString &method, const QJsonArray &params, int id);
};

#endif // JSONRPCCLIENT_H
JsonRpcClient.cpp
#include "JsonRpcClient.h"
#include <QTcpSocket>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>

JsonRpcClient::JsonRpcClient(const QString &host, quint16 port, QObject *parent) : QObject(parent), host(host), port(port) {
    socket = new QTcpSocket(this);
    connect(socket, &QTcpSocket::connected, this, &JsonRpcClient::onConnected);
    connect(socket, &QTcpSocket::readyRead, this, &JsonRpcClient::onReadyRead);
    connect(socket, &QTcpSocket::errorOccurred, this, &JsonRpcClient::onErrorOccurred);
    socket->connectToHost(host, port);
}

JsonRpcClient::~JsonRpcClient() {
    if (socket->isOpen()) {
        socket->close();
    }
}

void JsonRpcClient::onConnected() {
    qDebug() << "Connected to server";

    // Send a simple 'add' request
    QJsonArray params;
    params.append(5);
    params.append(10);
    sendRequest("add", params, 1);
}

void JsonRpcClient::onReadyRead() {
    QByteArray response = socket->readAll();
    processResponse(response);
}

void JsonRpcClient::onErrorOccurred(QAbstractSocket::SocketError socketError) {
    qWarning() << "Socket error:" << socketError;
}

void JsonRpcClient::sendRequest(const QString &method, const QJsonArray &params, int id) {
    QByteArray request = createJsonRpcRequest(method, params, id);
    socket->write(request);
}

void JsonRpcClient::processResponse(const QByteArray &response) {
    QJsonDocument doc = QJsonDocument::fromJson(response);
    if (doc.isObject()) {
        QJsonObject responseObj = doc.object();
        if (responseObj.contains("result")) {
            qDebug() << "Result:" << responseObj["result"];
        } else {
            qDebug() << "Error in response:" << responseObj["error"];
        }
    }
}

QByteArray JsonRpcClient::createJsonRpcRequest(const QString &method, const QJsonArray &params, int id) {
    QJsonObject request;
    request["jsonrpc"] = "2.0";
    request["method"] = method;
    request["params"] = params;
    request["id"] = id;

    QJsonDocument doc(request);
    return doc.toJson();
}

Logo

一起探索未来云端世界的核心,云原生技术专区带您领略创新、高效和可扩展的云计算解决方案,引领您在数字化时代的成功之路。

更多推荐