首页 > 其他分享 >开源库:jcon-cpp

开源库:jcon-cpp

时间:2025-01-10 18:01:07浏览次数:1  
标签:jcon auto rpc server 开源 client cpp new

说明

jcon-cpp 是一个用于 C++ 的 JSON-RPC 库,它允许开发者通过 JSON-RPC 协议进行进程间通信(IPC)。JSON-RPC 是一种轻量级的远程过程调用协议,基于 JSON 格式数据进行通信。基于MIT协议,最新代码基于Qt6实现。可通过Tcp和WebSocket实现RPC。

调整源码以适配Qt5

  • 修改json_rpc_server.cppdoCall函数实现,将QMetaType return_type = QMetaType::fromName(return_type_name)改为int return_type = QMetaType::type(return_type_name)
  • 修改json_rpc_websocket.cppsetupSocket函数实现,将void (QWebSocket::*errorPtr)(QAbstractSocket::SocketError) = &QWebSocket::errorOccurred;修改为void (QWebSocket::*errorPtr)(QAbstractSocket::SocketError) = &QWebSocket::error;

创建基于TCP的RPC服务器

示例代码

jcon::JsonRpcServer* startServer(QObject* parent, SocketType socket_type = SocketType::tcp, bool allow_notifications = false)
{
    jcon::JsonRpcServer* rpc_server;
    if (socket_type == SocketType::tcp) {
        qDebug() << "Starting TCP server";
        rpc_server = new jcon::JsonRpcTcpServer(parent);
    } else {
        qDebug() << "Starting WebSocket server";
        rpc_server = new jcon::JsonRpcWebSocketServer(parent);
    }

    if (allow_notifications)
        rpc_server->enableSendNotification(true);

    auto service1 = new ExampleService;
    auto service2 = new NotificationService;

    rpc_server->registerServices({ service1, service2 });
    rpc_server->listen(6002);
    return rpc_server;
}

auto server = startServer(nullptr, SocketType::tcp);
//do something 
delete server;

说明

  • rpc_server->enableSendNotification(true),用于设置RPC服务器是否可以主动推送消息给客户端

  • ExampleService、NotificationService都是QObject子类,通过元对象系统来定义、存储、调用相关接口,所以接口前需要定义成Q_INVOKABLE

    #pragma once
    #include <QObject>
    
    class ExampleService : public QObject
    {
        Q_OBJECT
    
    public:
        ExampleService();
        virtual ~ExampleService();
    
        Q_INVOKABLE int getRandomInt(int limit);
        Q_INVOKABLE QString printMessage(const QString& msg);
        Q_INVOKABLE void printNotification(const QString& msg);
        Q_INVOKABLE void namedParams(QString& msg, int answer);
    };
    
  • rpc_server->registerServices,将接口服务类注册到RPC服务器中,有两种方式:注册普通服务、注册命名空间服务。

    //注册普通服务
    //m_services结构为QMap<QObject*, QString>,此时key存储的是QObject接口类,value为空
    void JsonRpcServer::registerServices(const QObjectList& services)
    {
        m_services.clear();
    
        for (auto s : services) {
            m_services[s] = "";
        }
        m_ns_separator = "";
    }
    
    //调用
    auto service1 = new ExampleService;
    auto service2 = new NotificationService;
    rpc_server->registerServices({ service1, service2 });
    
    
    //注册命名空间服务
    //m_services结构为QMap<QObject*, QString>,此时key存储的是QObject接口类,value为对应服务的命名空间字符串
    //ns_separator是一个用于分隔命名空间和方法名的字符串,默认为 /
    void JsonRpcServer::registerServices(const ServiceMap& services,
                                         const QString& ns_separator)
    {
        m_services = services;
        m_ns_separator = ns_separator;
    }
    
    //调用
    auto service1 = new ExampleService;
    auto service2 = new OtherService;
    auto service3 = new NotificationService;
    rpc_server->registerServices(
    {
    	{ service1, "ex/myFirstNamespace" },
    	{ service2, "ex/myOtherNamespace" },
    	{ service3, "ex/myNotificationNamespace" }
    }, "/");
    
  • rpc_server->listen(6002)监听某端口,JsonRpcServer有两个子类:JsonRpcTcpServer、JsonRpcWebSocketServerJsonRpcTcpServer实际就是实现了一个QTcpServer监听端口、客户端连接时创建Socket对象、Socket有请求时通过元对象系统找到对应的函数执行并返回结果

    /*class JsonRpcTcpServer*/
    
    //1.JsonRpcTcpServer构造函数,处理客户端连接
    m_server.connect(&m_server, &QTcpServer::newConnection, this, &JsonRpcTcpServer::newConnection);
    
    //2.JsonRpcTcpServer::newConnection,创建相关通信对象
    QTcpSocket* tcp_socket = m_server.nextPendingConnection();
    auto rpc_socket = std::make_shared<JsonRpcTcpSocket>(tcp_socket);
    auto endpoint = std::shared_ptr<JsonRpcEndpoint>(new JsonRpcEndpoint(rpc_socket, log(), this), [this](JsonRpcEndpoint* obj) {
    	if (this->m_server.isListening()) {
    		obj->deleteLater();
    	} else {
    		delete obj;
    	}
    });
    connect(endpoint.get(), &JsonRpcEndpoint::jsonObjectReceived, this, &JsonRpcServer::jsonRequestReceived);
    
    //3.JsonRpcServer::jsonRequestReceived,处理客户端请求
    //request是请求数据,json格式;socket是对应的通信对象
    void JsonRpcServer::jsonRequestReceived(const QJsonObject& request, QObject* socket)
    {
    	//校验json的key:jsonrpc
    	if (request.value("jsonrpc").toString() != "2.0") {
            logError("invalid protocol tag");
            return;
    	}
    	//获取json的key:method
    	QString method_name = request.value("method").toString();
    	//获取json的key:params
    	QVariant params = request.value("params").toVariant();
    	//获取json的key:id
    	QString request_id = request.value("id").toVariant().toString();
    	
    	//从存储的元对象中找到对应的函数并执行
    	dispatch(method_name, params, return_value)
    }
    
    
    

    创建基于TCP的RPC客户端

    示例代码

    jcon::JsonRpcClient* startClient(QObject* parent,
                                     SocketType socket_type = SocketType::tcp,
                                     bool allow_notifications = false)
    {
        jcon::JsonRpcClient* rpc_client;
        if (socket_type == SocketType::tcp) {
            rpc_client = new jcon::JsonRpcTcpClient(parent);
            rpc_client->connectToServer("127.0.0.1", 6002);
        } else {
            rpc_client = new jcon::JsonRpcWebSocketClient(parent);
            // This is just to illustrate the fact that connectToServer also accepts
            // a QUrl argument.
            rpc_client->connectToServer(QUrl("ws://127.0.0.1:6002"));
        }
    
        if (allow_notifications)
            rpc_client->enableReceiveNotification(true);
    
        return rpc_client;
    }
    
    auto rpc_client = startClient(&app, SocketType::tcp);
    

    说明

    • 调用通知类接口,无返回,通过函数名调用
    rpc_client->notification("printNotification", "hello, notification");
    
    • 异步调用接口,有返回,通过函数名调用
    auto req = rpc_client->callAsync("getRandomInt", 10);
    
    req->connect(req.get(), &jcon::JsonRpcRequest::result,
    			 [](const QVariant& result) {
    				 qDebug() << "result of asynchronous RPC call:" << result;
    			 });
    
    req->connect(req.get(), &jcon::JsonRpcRequest::error,
    			 [](int code, const QString& message) {
    				 qDebug() << "RPC error:" << message
    						  << " (" << code << ")";
    			 });
    
    • 同步调用接口,有返回,通过函数名调用
    auto result = rpc_client->call("getRandomInt", 100);
    
    if (result->isSuccess()) {
        qDebug() << "result of synchronous RPC call:" << result->result();
    } else {
        qDebug() << "RPC error:" << result->toString();
    }
    
    //call里通过事件循环等待完成
    
    • 异步调用接口,参数命名化方式,有返回,通过函数名调用
    //将参数存入QVariantMap,参数1是msg,参数2是answer
    auto req = rpc_client->callAsyncNamedParams("namedParams",
                                                QVariantMap{
                                                    {"msg", "hello, world"},
                                                    {"answer", 42}
                                                });
    
    req->connect(req.get(), &jcon::JsonRpcRequest::result,
                 [](const QVariant& result) {
                     qDebug() << "result of asynchronous RPC call:" << result;
                 });
    
    req->connect(req.get(), &jcon::JsonRpcRequest::error,
                 [](int code, const QString& message) {
                     qDebug() << "RPC error:" << message
                              << " (" << code << ")";
                 });
    

标签:jcon,auto,rpc,server,开源,client,cpp,new
From: https://www.cnblogs.com/judes/p/18664439

相关文章

  • 目标客户营销(ABM)结合开源AI智能名片2+1链动模式S2B2C商城小程序的策略与实践
    摘要:在数字化营销日益盛行的今天,目标客户营销(AccountBasedMarketing,ABM)作为一种高度定制化的营销策略,正逐步成为企业获取高质量客户、提升市场竞争力的重要手段。与此同时,开源AI智能名片2+1链动模式S2B2C商城小程序作为一种创新的数字化营销工具,以其强大的数据分析、智能推......
  • 基于开源AI智能名片2+1链动模式S2B2C商城小程序的企业数字化转型深度策略与实践
    摘要:在大数据、人工智能等前沿技术的推动下,企业数字化转型已成为提升竞争力的关键路径。开源AI智能名片2+1链动模式S2B2C商城小程序作为一种创新工具,凭借其强大的数据分析、智能推荐及社交裂变能力,为企业提供了一个从用户洞察、产品优化到供应链管理的全方位解决方案。本文旨在......
  • 开源飞控之量产固件烧录&品质测试讨论
    开源飞控之量产固件烧录&品质测试讨论1.源由2.核心目标2.1实时数据采集与追踪2.2质量管理2.3设备管理2.4工艺与流程控制2.5异常管理与报警机制3.工程技术3.1固件烧录3.2品质测试3.3数据分析4.总结1.源由智能产品(IT产品)的大规模生产早在笔者从业2006......
  • 一个适用于 .NET 的开源整洁架构项目模板
    前言项目架构模式在软件开发中扮演着至关重要的角色,它们为开发者提供了一套组织和管理代码的指导原则,以提高软件的可维护性、可扩展性、可重用性和可测试性。今天大姚给大家分享一个适用于.NET的开源整洁架构项目模板。.NET常见的几种项目架构模式https://mp.weixin.qq.com/s......
  • cpp智能指针
      普通指针的不足new和new[]的内存需要用delete和deletel]释放。程序员的主观失误,忘了或漏了释放。程序员也不确定何时释放。普通指针的释放类内的指针,在析构函数中释放。C++内置数据类型,如何释放?new出来的类,本身如何释放?C++11新增三个智能指针类型uniqu......
  • 【开源】C#上位机必备高效数据转换助手
    一、前言大家好!我是付工。我们在进行上位机开发时,从设备端获取到的数据之后,需要进行一定的数据处理及转换,才能生成我们需要用的数据。这其中就涉及到了各种数据类型之间的相关转换,很多非科班出身的电气工程师,经常会因为弄不清楚各种数据类型之间的转换关系,导致无法获取到自己想......
  • JAVA开源免费项目 基于Vue和SpringBoot的常规应急物资管理系统(附源码)
    本文项目编号T159,文末自助获取源码\color{red}{T159,文末自助获取源码}......
  • JAVA开源免费项目 基于Vue和SpringBoot的线上辅导班系统(附源码)
    本文项目编号T160,文末自助获取源码\color{red}{T160,文末自助获取源码}......
  • 无需昂贵GPU:本地部署开源AI项目LocalAI你在消费级硬件上运行大模型
    前言本文主要介绍如何在本地服务器部署无需依托高昂价格的GPU,也可以在本地运行离线AI项目的开源AI神器LoaclAI,并结合cpolar内网穿透轻松实现远程使用的超详细教程。随着AI大模型的发展,各大厂商都推出了自己的线上AI服务,比如写文章的、文字生成图片或者视频的......
  • 【开源】基于SpringBoot框架公司日常考勤系统(计算机毕业设计)+万字毕业论文 T134
    系统合集跳转源码获取链接一、系统环境运行环境:最好是javajdk1.8,我们在这个平台上运行的。其他版本理论上也可以。IDE环境:Eclipse,Myeclipse,IDEA或者SpringToolSuite都可以tomcat环境:Tomcat7.x,8.x,9.x版本均可操作系统环境:WindowsXP/7/8//8.1/10/11或者L......