项目日记 -云备份 -服务器配置信息模块

news2025/3/25 21:50:33

博客主页:【夜泉_ly】
本文专栏:【项目日记-云备份】
欢迎点赞👍收藏⭐关注❤️

在这里插入图片描述
代码已上传 gitee

目录

  • 前言
  • 配置信息文件
  • 文件配置类
    • getInstance 获得实例
    • readConfigFile 读取配置信息文件
  • 测试

前言

在之前的文章中,
我已经实现了服务端的实用工具类,
本篇。。
等等,先说一下,
我将之前工具类的成员函数名全改了,
从首字母大写变成了首字母小写,
至于原因。。。这样更顺眼一些?

本篇将实现服务器配置信息模块,
由一个配置信息文件,
和一个文件配置类组成。

配置信息文件

开始前,我们必须知道,
为什么我们需要这个模块?
或者说,为什么我们需要配置信息文件?

举个简单的例子——服务器 ip 地址,
如果无配置信息文件,
当程序想跑在不同服务器上时,
还得手动去改代码中的赋值;
当我们将服务器 ip 地址写入配置信息文件,
那么程序启动时只需读取这个文件,
我们想修改 ip 地址也只用改这个文件。

所以,配置信息文件必须要有:
CloudBackup/src/config.conf

{
    "hot_time" : 10,
    "server_port" : 8899,
    "server_ip" : "113.44.51.126",
    "download_prefix" : "/download/",
    "packfile_suffix" : ".lz",
    "pack_dir" : "./packdir/",
    "back_dir" : "./backdir/",
    "backup_file" : "./cloud.dat"
}

简单解释一下:

KV
hot_time多长时间没访问算热文件(测试时可以设短一点,比如10秒)
server_port服务端的端口号
server_ip服务器的ip地址
download_prefix如果客户端传来的url带这个前缀,说明他要下载文件
packfile_suffix压缩包的后缀名(毕竟压缩格式可能会变)
pack_dir放备份文件的目录
back_dir放已经被压缩的非热点文件的目录
backup_file存放所有备份文件的信息,的文件

如果你是第一次看,可能会很懵,
不过没关系,之后用多了就不会懵了。

文件配置类

接下来,为了更好的管理这些数据,
需要写个文件配置类,大概长这样:
CloudBackup/src/config.conf

#pragma once
#include "utils.hpp"
#include <mutex>

namespace Cloud {
#define CONFIG_FILE_PATH "./config.conf"
class Config {
public:
    static Config* getInstance();
    const size_t getHotTime() const { return _hotTime; }
    const size_t getServerPort() const { return _serverPort; }
    const std::string& getServerIp() const { return _serverIp; }
    const std::string& getDownloadPrefix() const { return _downloadPrefix; }
    const std::string& getPackfileSuffix() const { return _packfileSuffix; }
    const std::string& getPackDir() const { return _packDir; }
    const std::string& getBackDir() const { return _backDir; }
    const std::string& getBackupFile() const { return _backupFile; }
    void updata() { readConfigFile(); }
    void show() const ;
    
private:
    Config() { readConfigFile(); }
    Config(const Config&) = delete;
    Config operator=(const Config&) = delete;
    void readConfigFile();

private:
    size_t _hotTime;
    size_t _serverPort;
    std::string _serverIp;
    std::string _downloadPrefix;
    std::string _packfileSuffix;
    std::string _packDir;
    std::string _backDir;
    std::string _backupFile;

private:
    static Config* _instance;
    static std::mutex _mutex;
};
std::mutex Config::_mutex;
Config* Config::_instance = nullptr;
} // namespace Cloud

想必你已经看出来了,这是个单例类,
(毕竟配置信息只可能有一份),
用的是懒汉模式,
即需要的时候再 new 出来,
同时,deleteCopying 函数,
防止有人乱搞。

宏定义:
CONFIG_FILE_PATH 配置信息文件的路径(这个只能手写,没办法)

成员函数:
getInstance 获得实例
getXXX 获得XXX
update 更新配置信息(万一想在服务器运行时改配置信息呢?所以写了这个)
show 展示配置信息(这个是用来测试的,可以删)
readConfigFile 读取配置信息文件

成员变量:
一堆配置信息,
一个指针,
一把锁。

getInstance 获得实例

static Config *getInstance()
{
    if (_instance == nullptr)
    {
        _mutex.lock();
        if (_instance == nullptr)
            _instance = new Config();
        _mutex.unlock();
    }
    return _instance;
}

if
第一个if防止明明有实例了,
还要加锁再判断;
第二个if防止多个线程挤在lock处,
之后拿到锁后看都不看就new个新的实例。

readConfigFile 读取配置信息文件

void readConfigFile()
{
    std::string config;
    if (FileUtils(CONFIG_FILE_PATH).getContent(&config) == false)
    {
        std::cout << "Read config file error\n";
        return;
    }
    Json::Value root;
    JsonUtils::deSerialize(config, &root);
    _hotTime = root["hot_time"].asInt64();
    _serverPort = root["server_port"].asInt64();
    _serverIp = root["server_ip"].asString();
    _downloadPrefix = root["download_prefix"].asString();
    _packfileSuffix = root["packfile_suffix"].asString();
    _packDir = root["pack_dir"].asString();
    _backDir = root["back_dir"].asString();
    _backupFile = root["backup_file"].asString();
    std::cout << "read Config file done\n"; // 可以注释掉
    show(); // 可以注释掉
}

最后两行,虽然我说可以注释掉,
但其实还是有点必要的,

万一,
你哪天心血来潮,
想改改配置信息文件,
比如把 "hot_time" 改成了 "hotTime"
但你忘记改 readConfigFile 了!
它读的时候是不会报错的,
而是直接把你的 _hotTime 设置为 0。

你应该也不想在各个类里面查了很久的bug,
最后发现是配置信息根本没读上来吧?
在这里插入图片描述
show 展示配置信息

void show() const
{
    std::cout << "hotTime:        " << _hotTime << std::endl;
    std::cout << "serverPort:     " << _serverPort << std::endl;
    std::cout << "serverIp:       " << _serverIp << std::endl;
    std::cout << "downloadPrefix: " << _downloadPrefix << std::endl;
    std::cout << "packfileSuffix: " << _packfileSuffix << std::endl;
    std::cout << "packDir:        " << _packDir << std::endl;
    std::cout << "backDir:        " << _backDir << std::endl;
    std::cout << "backupFile:     " << _backupFile << std::endl;
}

测试

这个模块的测试很简单:

#include "config.hpp"
int main()
{
    Cloud::Config::getInstance();
    return 0;
}

在这里插入图片描述
在这里插入图片描述


希望本篇文章对你有所帮助!并激发你进一步探索编程的兴趣!
本人仅是个C语言初学者,如果你有任何疑问或建议,欢迎随时留言讨论!让我们一起学习,共同进步!

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

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

相关文章

Mysql配套测试之查询篇

&#x1f3dd;️专栏&#xff1a;Mysql_猫咪-9527的博客-CSDN博客 &#x1f305;主页&#xff1a;猫咪-9527-CSDN博客 “欲穷千里目&#xff0c;更上一层楼。会当凌绝顶&#xff0c;一览众山小。” 目录 条件查询简单测试&#xff1a; 1.查询英语成绩不及格的同学(<60) 2…

mysql——第二课

学生表 CREATE TABLE student (id int(11) NOT NULL AUTO_INCREMENT,name varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,sex varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,age int(11) DEFAULT NULL,c_id int(10) DEFAULT NULL,PRIMARY KEY (id),KEY c_id (c_id),CONSTR…

Python网络编程入门

一.Socket 简称套接字&#xff0c;是进程之间通信的一个工具&#xff0c;好比现实生活中的插座&#xff0c;所有的家用电器要想工作都是基于插座进行&#xff0c;进程之间要想进行网络通信需要Socket&#xff0c;Socket好比数据的搬运工~ 2个进程之间通过Socket进行相互通讯&a…

arm linux下的读写信号量rw_semphore的实现

本文基于arm linux 5.10来介绍内核中使用的读写信号量rw remphore的实现代码。 内核中信号量结构体struct rw_semaphore的定义在include/linux/rwsem.h 32位architectures下&#xff0c;结构体struct rw_semaphore中的count的使用如下&#xff1a; 先来看信号量的定义和初始化…

C#里使用libxl的数字格式

由于EXCEL里可以表示不同的数字格式, 比如表示货币数字时,与表示普通序号的数字就不一样。 还有科学计算表示的数字使用小数点位数与普通货币也不一样。 如下所示: 要使用这些格式, 下面创建一个例子来演示保存这些数字格式: private void button11_Click(object send…

c#难点整理2

1.对象池的使用 就是先定义一系列的对象&#xff0c;用一个&#xff0c;调一个。 public class ObjectPool<T> where T : new(){private Queue<T> pool; // 用于存储对象的队列private int maxSize; // 对象池的最大容量// 构造函数public ObjectPool(int maxSi…

解锁物联网高效开发,Synaptics SYN43756E Wi-Fi 6E 芯片登场

Synaptics 的 SYN43756E 芯片是一款高性能的 Wi-Fi 6E 支持 11a/b/g/n/ac/ax 的物联网&#xff08;IoT&#xff09;SoC&#xff0c;具备多项先进特性&#xff0c;适用于多种应用场景&#xff0c;以下是其主要优势&#xff1a; 1. 广泛的应用场景 智慧家庭&#xff1a;支持多种…

DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加导出数据功能

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加导出数据功能📚页面效果📚指令输入�…

2024年河南省职业院校 技能大赛高职组 “大数据分析与应用” 赛项任务书(四)

2024 年河南省职业院校 技能大赛高职组 “大数据分析与应用” 赛项任务书&#xff08;四&#xff09;&#xff09; 背景描述&#xff1a;任务一&#xff1a;Hadoop 完全分布式安装配置&#xff08;25 分&#xff09;任务二&#xff1a;离线数据处理&#xff08;25 分&#xff0…

dify创建第一个Agent

1、首先LLM模型必须支持 Function Calling 由于deepseek-R1本地化部署时还不支持&#xff0c;所以使用 qwq模型。 2、创建空白 Agent 3、为Agent添加工具 4、测试 当未添加时间工具时 询问 时间 如下 5、开启时间工具 询问如下

⭐算法OJ⭐判断二叉搜索树【树的遍历】(C++实现)Validate Binary Search Tree

图论入门【数据结构基础】&#xff1a;什么是树&#xff1f;如何表示树&#xff1f; 之前我们有分别讲解二叉树的三种遍历的相关代码实现&#xff1a; ⭐算法OJ⭐二叉树的前序遍历【树的遍历】&#xff08;C实现&#xff09;Binary Tree Preorder Traversal ⭐算法OJ⭐二叉树的…

2. 商城前端部署

商城客户端前端部署 https://gitee.com/newbee-ltd/newbee-mall-api-go 使用开源新蜂商城的前端&#xff0c;git clone到本地 然后在vscode终端依次输入下列指令&#xff08;配置好vue3相关环境的前提下&#xff09;&#xff1a; npm install npm i --legacy-peer-deps npm …

鸿蒙生态开发

鸿蒙生态开发概述 鸿蒙生态是华为基于开源鸿蒙&#xff08;OpenHarmony&#xff09;构建的分布式操作系统生态&#xff0c;旨在通过开放共享的模式连接智能终端设备、操作系统和应用服务&#xff0c;覆盖消费电子、工业物联网、智能家居等多个领域。以下从定义与架构、核心技术…

基于STM32进行FFT滤波并计算插值DA输出

文章目录 一、前言背景二、项目构思1. 确定FFT点数、采样率、采样点数2. 双缓存设计 三、代码实现1. STM32CubeMX配置和HAL库初始化2. 核心代码 四、效果展示和后话五、项目联想与扩展1. 倍频2. 降频3. 插值3.1 线性插值3.2 样条插值 一、前言背景 STM32 对 AD 采样信号进行快…

【Oracle资源损坏类故障】:详细了解坏块

目录 1、物理坏块与逻辑坏块 1.1、物理坏块 1.2、逻辑坏块 2、两个坏块相关的参数 2.1、db_block_checksum 2.2、db_block_checking 3、检测坏块 3.1、告警日志 3.2、RMAN 3.3、ANALYZE 3.4、数据字典 3.5、DBVERIFY 4、修复坏块 4.1、RMAN修复 4.2、DBMS_REPA…

996引擎-接口测试:背包

996引擎-接口测试:背包 背包测试NPC参考资料背包测试NPC CONSTANT = require("Envir/QuestDiary/constant/CONSTANT.lua"); MsgUtil = require("Envir/QuestDiary/utils/996/MsgUtil.lua");

Electron打包文件生成.exe文件打开即可使用

1 、Electron 打包&#xff0c;包括需要下载的内容和环境配置步骤 注意&#xff1a;Electron 是一个使用 JavaScript、HTML 和 CSS 构建跨平台桌面应用程序的框架 首先需要电脑环境有Node.js 和 npm我之前的文章有关nvm下载node的说明也可以去官网下载 检查是否有node和npm环…

单播、广播、组播和任播

文章目录 一、单播二、广播三、组播四、任播代码示例&#xff1a; 五、各种播的比较 一、单播 单播&#xff08;Unicast&#xff09;是一种网络通信方式&#xff0c;它指的是在网络中从一个源节点到一个单一目标节点对的传输模式。单播传输时&#xff0c;数据包从发送端直接发…

Cursor+Claude-3.5生成Android app

一、Android Studio下载 https://developer.android.com/studio?hlzh-tw#get-android-studio 等待安装完成 二、新建工程 点击new project 选择Empty Activity 起一个工程名 当弹出这个框时 可以在settings里面选择No proxy 新建好后如下 点击右边模拟器&#xff0c…

QT Quick(C++)跨平台应用程序项目实战教程 3 — 项目基本设置(窗体尺寸、中文标题、窗体图标、可执行程序图标)

目录 1. 修改程序界面尺寸和标题 2. 窗体图标 3. 修改可执行程序图标 上一章创建好了一个初始Qt Quick项目。本章介绍基本的项目修改方法。 1. 修改程序界面尺寸和标题 修改Main.qml文件&#xff0c;将程序宽度设置为1200&#xff0c;程序高度设置为800。同时修改程序标题…