JSON-RPC-CXX深度解析:C++中的远程调用利器

news2024/11/15 15:18:31

一、引言

1. JSON-RPC 简介及其在 C++ 开发中的重要性

JSON-RPC(JavaScript Object Notation - Remote Procedure Call)是一种基于 JSON 格式的远程过程调用协议。在 C++ 开发中,它扮演着至关重要的角色。随着软件系统的日益复杂和分布式架构的广泛应用,高效的远程过程调用成为构建强大应用程序的关键。JSON-RPC 以其简洁的 JSON 数据格式,使得不同的系统之间可以轻松地进行通信,而无需关心底层的网络细节和数据传输方式。

在 C++ 开发中,JSON-RPC 为开发者提供了一种跨平台、高效且灵活的远程调用解决方案。它允许 C++ 程序与其他语言编写的程序进行无缝交互,促进了多语言环境下的软件开发。同时,JSON-RPC 的轻量级特性使其在资源受限的环境中也能表现出色,适用于各种类型的 C++ 项目,从嵌入式系统到高性能服务器应用。

2. 引入 json-rpc-cxx 库的独特价值

json-rpc-cxx 库作为一个开源的 C++ 实现,为 C++ 开发者带来了诸多独特价值。首先,它严格遵循 JSON-RPC 协议,确保了与其他符合该协议的系统的兼容性。该库提供了丰富的功能,方便地定义可远程调用的函数,处理客户端和服务器之间的 JSON 数据序列化和反序列化,以及支持多种网络传输方式或可与其他网络库集成。

json-rpc-cxx 库的跨平台兼容性也是其一大优势。无论是在 Windows、Linux 还是 OSX 上,都能无缝运行,为开发者提供了极大的便利。此外,它利用了流行的 nlohmann::json 库,确保了数据处理的高效性和便捷性。同时,该库的设计充分考虑了类型安全和编译时错误检查,减少了运行时问题,提升了开发效率。

  • json-rpc-cxx 开源库链接

二、JSON-RPC-CXX 库概述

1. 严格遵循 JSON-RPC 协议,实现跨网络通信

json-rpc-cxx 库严格遵循 JSON-RPC 2.0 规范,确保了在不同的网络环境下,客户端和服务器能够进行稳定且高效的通信。通过使用 JSON 格式作为数据交换格式,它克服了不同编程语言和系统之间的差异,使得跨网络通信变得轻而易举。

JSON-RPC 协议定义了一种简洁而有效的方式来进行远程过程调用。在 json-rpc-cxx 库的实现中,客户端可以通过发送包含方法名和参数的 JSON 请求,向服务器发起远程调用。服务器接收到请求后,解析 JSON 数据,执行相应的方法,并将结果以 JSON 格式返回给客户端。这种方式不仅使得通信过程清晰明了,而且易于理解和调试。

2. 丰富功能列举

  • 方便定义远程调用函数:json-rpc-cxx 库提供了简洁的接口,使得开发者可以轻松地定义可远程调用的函数。通过继承 jsonrpccxx::JsonRpcServer 类,并使用 BindMethod 函数,开发者可以将 C++ 的函数绑定为远程可调用的方法。例如,可以像这样定义一个加法函数:BindMethod("add", [](int num1, int num2) { return num1 + num2; });。这种方式使得 C++ 程序中的函数可以被其他系统通过网络远程调用,极大地提高了程序的可扩展性和灵活性。
  • 处理 JSON 数据序列化反序列化:该库利用流行的 nlohmann::json 库,高效地处理 JSON 数据的序列化和反序列化。在客户端和服务器之间进行通信时,需要将数据转换为 JSON 格式进行传输。json-rpc-cxx 库能够自动地将 C++ 的数据类型转换为 JSON 格式,并在接收到 JSON 数据时,将其反序列化为 C++ 的数据类型。这样,开发者无需手动处理数据的转换过程,大大提高了开发效率。
  • 支持多种网络传输方式:json-rpc-cxx 库具有很强的灵活性,支持多种网络传输方式。它可以与不同的网络库集成,如 HTTP、WebSocket 等。这使得开发者可以根据具体的应用场景选择最适合的网络传输方式。例如,在需要实时通信的场景下,可以选择 WebSocket 传输方式;而在传统的基于请求 - 响应的场景下,HTTP 可能是更好的选择。这种灵活性使得 json-rpc-cxx 库能够适应各种不同的网络环境和应用需求。

三、服务器端应用

在构建基于json-rpc-cxx库的服务器端应用时,我们需要关注几个关键步骤:创建服务器、定义服务方法以及启动服务器。下面将详细介绍这些步骤。

(一)创建服务器

包含必要头文件及作用介绍

在服务器端代码中,包含的头文件如jsonrpccxx/server.hjsonrpccxx/server_connector.h起着至关重要的作用。

  • jsonrpccxx/server.h:提供了创建服务器的类和相关函数,使我们能够构建一个JSON-RPC服务器实例,以监听客户端的请求并进行相应的处理。
  • jsonrpccxx/server_connector.h:提供了服务器连接相关的类和函数,用于实现服务器与客户端之间的连接管理。

以HttpServer为例创建服务器实例,监听指定端口

json-rpc-cxx库提供了不同类型的服务器类,以HttpServer为例,我们可以在特定端口创建服务器实例。假设我们要在端口8080创建服务器,可以使用以下代码:

jsonrpccxx::HttpServer httpServer(8080);

这样就创建了一个基于HTTP协议监听在8080端口的服务器对象,等待客户端的连接和请求。

(二)定义服务方法

创建继承JsonRpcServer的类,用于定义可被客户端调用的方法

为了定义可被客户端调用的方法,我们可以创建一个继承自jsonrpccxx::JsonRpcServer的类。这个类可以封装特定的业务逻辑,并将其暴露为远程可调用的方法。

通过BindMethod函数绑定具体方法,如加法函数示例

在继承自jsonrpccxx::JsonRpcServer的类中,我们可以使用BindMethod函数将C++的函数绑定到特定的方法名上。例如,定义一个加法函数并绑定到名为add的方法上,可以这样实现:

BindMethod("add", [](int num1, int num2) { return num1 + num2; });

这样,当客户端通过JSON-RPC请求调用add方法时,服务器将执行这个加法函数并返回结果。

(三)启动服务器

在main函数中启动服务器并保持运行的逻辑

main函数中,我们可以启动服务器并使其保持运行,以持续监听客户端的请求。

  1. 创建服务器实例和服务类实例
jsonrpccxx::HttpServerConnector serverConnector(8080);
MyService service(serverConnector);
  1. 调用StartListening启动服务器监听
service.StartListening();
std::cout << "Server started on port 8080." << std::endl;

当调用StartListening函数后,服务器会进入监听状态,等待客户端的连接和请求。一旦有请求到达,服务器会根据请求的方法名和参数执行相应的方法,并将结果返回给客户端。

  1. 保持服务器运行

为了保持服务器运行,可以使用一个循环,例如while (true) {}。这个循环只是一个简单的示例,在实际应用中,可能需要更好的服务器运行管理逻辑,比如使用信号处理来优雅地停止服务器。

  1. StartListening和StopListening函数的作用
  • StartListening:启动服务器的监听,使服务器开始接收客户端的请求。
  • StopListening:停止服务器的监听。在服务器运行过程中,如果需要停止服务器,可以调用这个函数来释放资源并结束服务器进程。

服务端示例

以下是使用json-rpc-cxx库创建服务器的详细代码示例:

#include <iostream>
#include "jsonrpccxx/server.h"
#include "jsonrpccxx/server_connector.h"
#include "jsonrpccxx/http_server_connector.h"

class MyService : public jsonrpccxx::JsonRpcServer
{
public:
    MyService(jsonrpccxx::ServerConnector& serverConnector)
        : jsonrpccxx::JsonRpcServer(serverConnector)
    {
        BindMethod("add", [](int num1, int num2) {
            return num1 + num2;
        });
    }
};

int main()
{
    jsonrpccxx::HttpServerConnector serverConnector(8080);
    MyService service(serverConnector);
    service.StartListening();
    std::cout << "Server started on port 8080." << std::endl;
    while (true) {}
    service.StopListening();
    return 0;
}

在这个示例中,我们创建了一个基于HTTP的服务器,定义了一个名为add的远程方法,该方法接受两个整数参数并返回它们的和。服务器启动后会一直运行,直到程序被手动终止。

四、客户端应用

在 JSON-RPC 通信中,客户端应用负责发起请求并处理服务器的响应。以下是如何使用 json-rpc-cxx 库来创建客户端应用并调用服务器上的远程方法的详细步骤。

(一)创建客户端连接

包含客户端所需头文件

在客户端代码中,首先需要包含必要的头文件。这些头文件提供了创建客户端和处理客户端连接相关功能的类和函数。

#include "jsonrpccxx/client.h"
#include "jsonrpccxx/client_connector.h"
#include "jsonrpccxx/http_client_connector.h"
  • jsonrpccxx/client.h 包含了客户端的主要实现类,如 jsonrpccxx::JsonRpcClient,用于发起远程过程调用。
  • jsonrpccxx/client_connector.h 提供了客户端连接的相关类,用于建立与服务器的连接。
  • jsonrpccxx/http_client_connector.h 是具体的 HTTP 客户端连接器实现。

以 HttpClient 创建连接对象,指向服务器地址

接下来,使用 HttpClient 创建客户端连接对象。假设服务器在本地运行且监听在端口 8080,可以使用以下代码创建连接对象:

jsonrpccxx::HttpClientConnector client("http://127.0.0.1:8080");

这里创建了一个指向本地 8080 端口的 HTTP 客户端连接对象,为后续创建 JSON-RPC 客户端实例和调用远程方法提供了基础。

(二)创建 JSON-RPC 客户端实例

使用创建好的客户端连接对象,可以创建 jsonrpccxx::JsonRpcClient 实例:

jsonrpccxx::JsonRpcClient rpcClient(client);

这个实例将用于调用服务器上的远程方法。通过这个实例,客户端可以发起 JSON-RPC 请求,将方法名和参数发送给服务器,并接收服务器返回的结果。

(三)调用远程方法

通过 CallMethod 函数调用服务器方法,处理可能的异常

通过 rpcClient 可以调用服务器上的方法。例如,调用 add 方法:

try
{
    int result = rpcClient.CallMethod<int>("add", 3, 4);
    std::cout << "Result of add: " << result << std::endl;
}
catch (const jsonrpccxx::JsonRpcException& e)
{
    std::cerr << "JSON-RPC Exception: " << e.what() << std::endl;
}

在上述代码中,CallMethod 函数用于调用服务器上的方法。它的模板参数指定了返回值类型,第一个参数是要调用的方法名称,后面的参数是传递给方法的参数。这里调用 add 方法并传递 34 作为参数。如果调用过程中出现 JSON-RPC 相关的异常,会被 catch 块捕获并输出错误信息。

客户端示例

以下是使用 json-rpc-cxx 库创建 HTTP 客户端的详细代码示例:

#include <iostream>
#include "jsonrpccxx/client.h"
#include "jsonrpccxx/client_connector.h"
#include "jsonrpccxx/http_client_connector.h"

int main()
{
    // 创建 HTTP 客户端连接对象,连接到服务器(假设服务器在本地,端口为 8080)
    jsonrpccxx::HttpClientConnector client("http://127.0.0.1:8080");

    // 创建 JSON-RPC 客户端实例
    jsonrpccxx::JsonRpcClient rpcClient(client);

    try
    {
        // 调用服务器上的某个方法,这里假设服务器有一个名为 'add' 的方法,接受两个整数参数
        int result = rpcClient.CallMethod<int>("add", 3, 4);
        std::cout << "Result of add: " << result << std::endl;
    }
    catch (const jsonrpccxx::JsonRpcException& e)
    {
        std::cerr << "JSON-RPC Exception: " << e.what() << std::endl;
    }

    return 0;
}

在这个示例中,客户端连接到本地运行在 8080 端口的 HTTP 服务器,并调用服务器上定义的 add 方法,传入两个参数 34,然后输出结果。如果调用过程中出现 JSON-RPC 相关的异常,会被捕获并输出错误信息。

五、错误处理

在分布式应用程序中,错误处理是确保系统稳定和可靠性的关键。无论是服务器端还是客户端,都需要对可能出现的错误进行细致处理。以下是如何在 JSON-RPC 应用程序中进行错误处理的详细指南。

(一)服务器端错误处理

方法内部对可能错误的处理

在服务器端方法内部,对可能出现的错误进行细致处理是确保系统稳定的关键。以除法运算为例,当方法涉及到可能出现除数为 0 的情况时,需要进行特别处理。

class MyService : public jsonrpccxx::JsonRpcServer
{
public:
    MyService(jsonrpccxx::ServerConnector& serverConnector)
        : jsonrpccxx::JsonRpcServer(serverConnector)
    {
        BindMethod("divide", [](int num1, int num2) {
            try {
                if (num2 == 0) {
                    throw std::runtime_error("Division by zero");
                }
                return num1 / num2;
            } catch (const std::exception& e) {
                // 将异常信息作为错误消息返回给客户端
                return std::string("Error: ") + e.what();
            }
        });
    }
};

在上述代码中,divide 方法通过 try-catch 块进行异常处理。如果除数为 0,会抛出 std::runtime_error 异常,并在 catch 块中将错误信息以字符串形式返回给客户端。

设置全局异常处理函数

除了在方法内部处理错误,设置全局异常处理函数可以进一步增强服务器的稳定性。

class MyService : public jsonrpccxx::JsonRpcServer
{
public:
    MyService(jsonrpccxx::ServerConnector& serverConnector)
        : jsonrpccxx::JsonRpcServer(serverConnector)
    {
        // 设置全局异常处理函数
        SetExceptionHandler([](const std::exception& e) {
            return std::string("Internal server error: ") + e.what();
        });

        BindMethod("divide", [](int num1, int num2) {
            if (num2 == 0) {
                throw std::runtime_error("Division by zero");
            }
            return num1 / num2;
        });
    }
};

这里设置的全局异常处理函数,在捕获到未在方法内部处理的异常时,会将错误信息以特定格式返回给客户端。这样,即使某个方法没有正确处理异常,也能通过全局异常处理函数向客户端返回有意义的错误信息。

(二)客户端错误处理

使用 try-catch 块捕获 JsonRpcException 异常

在客户端调用远程方法时,使用 try-catch 块捕获 jsonrpccxx::JsonRpcException 异常是一种良好的编程习惯。

try {
    // 调用远程方法的代码
} catch (const jsonrpccxx::JsonRpcException& e) {
    std::cerr << "JSON-RPC Exception: " << e.what() << std::endl;
    // 可以根据错误码进行更详细的处理
    if (e.Code() == -32602) {
        std::cerr << "Invalid parameters." << std::endl;
    } else if (e.Code() == -32603) {
        std::cerr << "Internal error." << std::endl;
    }
} catch (const std::exception& e) {
    std::cerr << "Standard Exception: " << e.what() << std::endl;
}

在上述代码中,当捕获到 JsonRpcException 异常时,首先输出异常信息。然后,根据异常中的错误码进行更详细的错误处理。通过这种方式,可以更准确地定位和处理客户端在调用远程方法时出现的问题。

同时捕获标准异常处理其他问题

除了捕获 JsonRpcException 异常,还需要捕获其他可能的标准异常,以处理网络连接等其他问题。例如,在上述代码中,同时捕获了 std::exception 异常。这样,当出现其他未知的异常情况时,也能进行适当的处理。

六、总结

JSON-RPC 库,尤其是 json-rpc-cxx,在构建分布式应用程序中展现出诸多优势。以下是对 JSON-RPC 库优势的总结以及实际应用中的扩展方向。

1. JSON-RPC 库的优势

  • 高效便捷的远程过程调用:JSON-RPC 库提供了高效且便捷的远程过程调用方式,使得不同节点之间的通信变得简单而直接。
  • 跨平台兼容性json-rpc-cxx 在 Windows、Linux 和 OSX 上都能无缝运行,提高了开发效率和应用的可移植性。
  • 出色的数据处理能力:利用流行的 nlohmann::json 库,高效地处理 JSON 数据的序列化和反序列化,确保了数据在网络传输中的准确性和高效性。
  • 丰富的功能和灵活的选择:支持多种网络传输方式,为不同的应用场景提供了灵活的选择。
  • 全面的错误处理机制:服务器端和客户端都可以进行详细的错误处理,提高了系统的稳定性和可维护性。

2. 实际应用中的扩展方向

  • 添加更多复杂的远程方法:根据项目需求,添加更多复杂的远程方法以满足不同的业务需求。
  • 优化性能:通过调整网络传输参数、优化数据处理算法等方式,提高系统的响应速度和吞吐量。
  • 实现安全机制:添加身份验证和授权机制,确保只有合法的用户才能访问特定的远程方法。加密通信也是提高系统安全性的重要手段。

3. 利用文档和示例代码的重要性

  • 文档的重要性:文档提供了详细的使用说明和功能介绍,帮助开发者快速上手并深入理解库的功能特点。
  • 示例代码的重要性:示例代码展示了具体的应用场景和使用方法,为开发者提供了实际的参考。通过深入研究文档和示例代码,开发者可以更好地掌握库的使用技巧,避免常见的错误,提高开发效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2240912.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

04 简单神经网络推导及实现(C++/C)

简单神经网络推导及实现&#xff08;C/C&#xff09; 代码见A simple neural network - stock price prediction as an example(C/C) 1. 主要模块 Neuron.h&#xff1a;用于声明神经元类和构造函数。Layer.h&#xff1a;用于声明网络层类和构造函数。NNet.h&#xff1a;用于…

Mybatis配置文件的增删改查功能

Mybatis配置文件的增删改查功能 查询—条件查询 //resources里面的org.example.mapper中的BrandMapper.xml文件 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://…

【2024软考架构案例题】你知道什么是 RESTful 风格吗?

&#x1f449;博主介绍&#xff1a; 博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家&#xff0c;WEB架构师&#xff0c;阿里云专家博主&#xff0c;华为云云享专家&#xff0c;51CTO 专家博主 ⛪️ 个人社区&#x…

51单片机应用开发---LCD1602显示应用

实现目标 1、了解LCD1602液晶屏&#xff1b; 2、掌握驱动程序的编写&#xff1b; 3. 具体目标&#xff1a;在屏幕上显示字符。 一、LCD1206概述 1.1 定义 LCD1602(Liquid Crystal Display)液晶显示屏是一种字符型液晶显示模块,可以显示ASCII码的标准字符和其它的一些内置…

如何修改npm包

前言 开发中遇到一个问题&#xff0c;配置 Element Plus 自定义主题时&#xff0c;添加了 ElementPlusResolver({ importStyle: "sass" }) 后&#xff0c;控制台出现报错&#xff0c;这是因为 Dart Sass 2.0 不再支持使用 !global 来声明新变量&#xff0c;虽然当前…

【原创】java+ssm+mysql校园疫情防控管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

Python模拟键盘输入,解放双手

文章目录 Python模拟键盘输入&#xff0c;解放双手一、引言二、pyautogui库的详细介绍1、安装与配置2、键盘输入函数3、特殊按键和组合键 三、实用示例1、自动填写表单2、自动发送邮件3、自动化数据录入 四、总结 Python模拟键盘输入&#xff0c;解放双手 一、引言 在自动化办…

人工智能时代下对人的价值反思?

一、员工价值物化 在现代企业的运作中&#xff0c;资本管理层之间的权力博弈与资源争夺有时呈现出了激烈的内斗态势。这种冲突不仅仅局限于单一部门内部&#xff0c;而是波及到跨部门乃至不同业务小组间的战略部署与资源配置上。各部门经理们既要竭力确保自身团队的利益最大化…

【Qt实现虚拟键盘】

Qt实现虚拟键盘 &#x1f31f;项目分析&#x1f31f;实现方式&#x1f31f;开发流程 &#x1f31f;项目分析 需求&#xff1a;为Linux环境下提供可便捷使用的虚拟键盘OS环境&#xff1a;Windows 7/11、CentOS 7开发语言&#xff1a;Qt/C IDE&#xff1a;QtCreator 、Qt5.14.2功…

APT 参与者将恶意软件嵌入 macOS Flutter 应用程序中

发现了一些恶意软件样本&#xff0c;这些样本据信与朝鲜民主主义人民共和国 (DPRK)&#xff08;又称北朝鲜&#xff09;有关&#xff0c;这些样本使用 Flutter 构建&#xff0c;Flutter 的设计可以对恶意代码进行混淆。JTL 深入研究了恶意代码的工作原理&#xff0c;以帮助保护…

双十一抢券风波:大学生300元提6000元电动车遭拒,谁该负责?

双十一购物狂欢节&#xff0c;本应是消费者享受优惠、商家提升销量的双赢时刻&#xff0c;但在河南郑州&#xff0c;发生了一起哭笑不得的抢券风波。一名大学生在双十一期间&#xff0c;通过某平台抢到了原价6099元电动车的直降优惠&#xff0c;只需支付300元就能将车骑回家。然…

三周精通FastAPI:37 包含 WSGI - Flask,Django,Pyramid 以及其它

官方文档&#xff1a;https://fastapi.tiangolo.com/zh/advanced/wsgi/ 包含 WSGI - Flask&#xff0c;Django&#xff0c;其它 您可以挂载多个 WSGI 应用&#xff0c;正如您在 Sub Applications - Mounts, Behind a Proxy 中所看到的那样。 为此, 您可以使用 WSGIMiddlewar…

【汇编语言】包含多个段的程序(二)—— 将数据、代码、栈放入不同的段

文章目录 前言1. 存在的两个问题2. 解决办法3. 示例代码3.1 程序说明3.1.1 定义多个段的方法3.1.2 对段地址的引用3.1.3 各种段完全是我们的安排 4. 总结结语 前言 &#x1f4cc; 汇编语言是很多相关课程&#xff08;如数据结构、操作系统、微机原理&#xff09;的重要基础。但…

初识Linux · 共享内存

目录 理解共享内存 Shared memmory code 理解共享内存 前文介绍的管道方式的通信&#xff0c;本文介绍的是进程通信的另外一种方式&#xff0c;即共享内存。但是这种通信方式的特点是只能本地通信&#xff0c;并且不像管道那样有保护机制&#xff0c;这里是没有的。 我们通…

【竞技宝】CS2-上海majorRMR:美洲区最后门票争夺战

北京时间2024年11月15日&#xff0c;上海major美洲区RMR正在如火如荼的进行之中。昨日一共进行了三场2-1组的比赛以及三场1-2组的比赛&#xff0c;决出三个正赛参赛名额的同时也确定了今日2-2组的参赛队伍&#xff0c;那么昨日的比赛战果如何呢&#xff1f;接下来小宝就为大家带…

实战:深入探讨 MySQL 和 SQL Server 全文索引的使用及其弊端

在数据库中处理大量文本数据时,包含搜索(例如查找包含特定单词的文本)往往是必需的。然而,直接使用 LIKE %text% 的方式在大数据量中进行模糊查询会造成性能瓶颈。为了解决这一问题,MySQL 和 SQL Server 提供了全文索引(Full-Text Indexing)功能,可以显著加速文本数据的…

蓝桥杯——数组

1、移动数组元素 package day3;import java.util.Arrays;public class Demo1 {public static void main(String[] args) {int[] arr {1,2,3,4,5,6};int k 2;int[] arr_new f(arr,k);for (int i : arr_new) {System.out.print(i",");}//或System.out.println();St…

人体存在感应器设置时间开启感应人存在开灯,失效

环境&#xff1a; 领普人体存在感应器 问题描述&#xff1a; 人体存在感应器设置时间开启感应人存在开灯,失效&#xff0c;设置下午5点&#xff0c;如果有人在5点前一直在这个区域&#xff0c;这个时候到了5点&#xff0c;就触发不了感应自动打开灯光。 解决方案&#xff1a…

常用命令之LinuxOracleHivePython

1. 用户改密 passwd app_adm chage -l app_adm passwd -x 90 app_adm -> 执行操作后&#xff0c;app_adm用户的密码时间改为90天有效期--查看该euser用户过期信息使用chage命令 --chage的参数包括 ---m 密码可更改的最小天数。为零时代表任何时候都可以更改密码。 ---M 密码…

基于yolov8、yolov5的车型检测识别系统(含UI界面、训练好的模型、Python代码、数据集)

摘要&#xff1a;车型识别在交通管理、智能监控和车辆管理中起着至关重要的作用&#xff0c;不仅能帮助相关部门快速识别车辆类型&#xff0c;还为自动化交通监控提供了可靠的数据支撑。本文介绍了一款基于YOLOv8、YOLOv5等深度学习框架的车型识别模型&#xff0c;该模型使用了…