云备份项目
Posted qnbk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了云备份项目相关的知识,希望对你有一定的参考价值。
云备份
云备份:自动将本地计算机上指定文件夹中需要备份的文件上传备份到服务器中。并且能够随时通过浏览器进行查看并且下载,其中下载过程支持断点续传功能,而服务器也会对上传文件进行热点管理,将非热点文件进行压缩存储,节省磁盘空间。
目标:们实现两端程序,其中包括部署在用户机的客户端程序,上传需要备份的文件,以及运行在服务器上的服务端程序,实现备份文件的存储和管理,两端合作实现总体的自动云备份功能。
服务端程序
负责功能
- 客户端上传的文件进行备份存储
- 能够对文件进行热点文件管理,对非热点文件进行压缩存储,节省磁盘空间
- 支持客户端浏览器查看访问文件列表。
- 支持客户端浏览器下载文件,并且下载支持断点续传。
模块划分
- 数据管理模块:负责服务器上备份文件的信息管理。
- 网络通信模块:搭建网络通信服务器,实现与客户端通信。
- 业务处理模块:针对客户端的各个请求进行对应业务处理并响应结果。
- 热点管理模块:负责文件的热点判断,以及非热点文件的压缩存储。
客户端程序
负责功能
- 能够自动检测客户机指定文件夹中的文件,并判断是否需要备份
- 将需要备份的文件逐个上传到服务器
模块划分
- 数据管理模块:负责客户端备份的文件信息管理,通过这些数据可以确定一个文件是否需要备份。
- 文件检测模块:遍历获取指定文件夹中所有文件路径名称。
- 网络通信模块:搭建网络通信客户端,实现将文件数据备份上传到服务器。
环境搭建
gcc7.3版本
sudo yum install centos-release-scl-rh centos-release-scl
sudo yum install devtoolset-7-gcc devtoolset-7-gcc-c++
source /opt/rh/devtoolset-7/enable
echo "source /opt/rh/devtoolset-7/enable" >> ~/.bashrc
安装jsoncpp库
sudo yum install epel-release
sudo yum install jsoncpp-devel
ls /usr/include/jsoncpp/json/
下载bundle数据压缩库
sudo yum install git
git clone https://github.com/r-lyeh-archived/bundle.git
下载 httplib 库
git clone https://github.com/yhirose/cpp-httplib.git
json
json 是一种数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。
举例:
char name = "jack";
int age = 18;
float score[3] = 88.5, 99, 58;
//json这种数据交换格式是将这多种数据对象组织成为一个字符串:
[
"name" : "jack",
"age" : 18,
"score" : [88.5, 99, 58]
,
"name" : "rose",
"age" : 20,
"score" : [88.5, 99, 58]
]
json 数据类型:对象,数组,字符串,数字
对象:使用花括号 括起来的表示一个对象。
数组:使用中括号 [] 括起来的表示一个数组。
字符串:使用常规双引号 “” 括起来的表示一个字符串
数字:包括整形和浮点型,直接使用。
jsoncpp
jsoncpp 库用于实现 json 格式的序列化和反序列化,完成将多个数据对象组织成为 json 格式字符串,以及将 json格式字符串解析得到多个数据对象的功能。
这其中主要借助三个类以及其对应的少量成员函数完成:
//Json数据对象类
class Json::Value
Value &operator=(const Value &other); //Value重载了[]和=,因此所有的赋值和获取数据都可以通过
Value& operator[](const std::string& key);//简单的方式完成 val["姓名"] = "小明";
Value& operator[](const char* key);
Value removeMember(const char* key);//移除元素
const Value& operator[](ArrayIndex index) const; //val["成绩"][0]
Value& append(const Value& value);//添加数组元素val["成绩"].append(88);
ArrayIndex size() const;//获取数组元素个数 val["成绩"].size();
std::string asString() const;//转string string name = val["name"].asString();
const char* asCString() const;//转char* char *name = val["name"].asCString();
Int asInt() const;//转int int age = val["age"].asInt();
float asFloat() const;//转float
bool asBool() const;//转 bool
;
//json序列化类,低版本用这个更简单
class JSON_API Writer
virtual std::string write(const Value& root) = 0;
class JSON_API FastWriter : public Writer
virtual std::string write(const Value& root);
class JSON_API StyledWriter : public Writer
virtual std::string write(const Value& root);
//json序列化类,高版本推荐,如果用低版本的接口可能会有警告
class JSON_API StreamWriter
virtual int write(Value const& root, std::ostream* sout) = 0;
class JSON_API StreamWriterBuilder : public StreamWriter::Factory
virtual StreamWriter* newStreamWriter() const;
//json反序列化类,低版本用起来更简单
class JSON_API Reader
bool parse(const std::string& document, Value& root, bool collectComments = true);
//json反序列化类,高版本更推荐
class JSON_API CharReader
virtual bool parse(char const* beginDoc, char const* endDoc,
Value* root, std::string* errs) = 0;
class JSON_API CharReaderBuilder : public CharReader::Factory
virtual CharReader* newCharReader() const;
jsoncpp 实现序列化
#include <iostream>
#include <sstream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>
int main()
const char *name = "jack";
int age = 18;
float score[] = 70,80,90;
Json::Value root;
root["name"] =name;
root["age"] = age;
root["score"].append(score[0]);
root["score"].append(score[1]);
root["score"].append(score[2]);
Json::StreamWriterBuilder swb;
std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
std::stringstream ss;
sw->write(root,&ss);
std::cout << ss.str() << std::endl;
return 0;
g++ json_example.cpp -o json_example -ljsoncpp
jsoncpp 实现反序列化
#include <iostream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>
int main()
std::string str = R"("name":"lily","age":20,"score":[10,30,20])";
Json::Value root;
Json::CharReaderBuilder crb;
std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
std::string err;
bool ret = cr->parse(str.c_str(),str.c_str()+str.size(),&root,&err);
if(ret == false)
std::cout<<"parse error"<<std::endl;
return -1;
std::cout<<root["name"].asString()<<std::endl;
std::cout<<root["age"].asString()<<std::endl;
int sz = root["score"].size();
for(int i = 0;i < sz;i++)
std::cout<<root["score"][i]<<std::endl;
return 0;
bundle文件压缩库
BundleBundle 是一个嵌入式压缩库,支持23种压缩算法和2种存档格式。使用的时候只需要加入两个文件bundle.h 和 bundle.cpp 即可。
namespace bundle
// low level API (raw pointers)
bool is_packed( *ptr, len );
bool is_unpacked( *ptr, len );
unsigned type_of( *ptr, len );
size_t len( *ptr, len );
size_t zlen( *ptr, len );
const void *zptr( *ptr, len );
bool pack( unsigned Q, *in, len, *out, &zlen );
bool unpack( unsigned Q, *in, len, *out, &zlen );
// medium level API, templates (in-place)
bool is_packed( T );
bool is_unpacked( T );
unsigned type_of( T );
size_t len( T );
size_t zlen( T );
const void *zptr( T );
bool unpack( T &, T );
bool pack( unsigned Q, T &, T );
// high level API, templates (copy)
T pack( unsigned Q, T );
T unpack( T );
bundle库实现文件压缩
cp bundle/bundle.cpp bundle/bundle.h Linux/cloude/
把bundle.cpp,bundle.h拷贝到当前操作的文件夹中
#include <iostream>
#include <string>
#include <fstream>
#include "bundle.h"
int main(int argc,char* argv[])
std::cout<<"argv[1]是原始路径名称"<<std::endl;
std::cout<<"argv[2]是压缩包名称"<<std::endl;
if(argc < 3)
return -1;
std::string ifilename = argv[1];
std::string ofilename = argv[2];
std::ifstream ifs;
ifs.open(ifilename,std::ios::binary);//打开原始文件
ifs.seekg(0,std::ios::end);//跳转读写位置到末尾
size_t fsize = ifs.tellg();//获取末尾偏移量--文件长度
ifs.seekg(0,std::ios::beg);//跳转到文件起始
std::string body;
body.resize(fsize);//调整body大小为文件大小
ifs.read(&body[0],fsize);//读取文件所有数据到body
std::string packed = bundle::pack(bundle::LZIP,body);//以lzip格式压缩文件数据
std::ofstream ofs;
ofs.open(ofilename,std::ios::binary);//打开压缩包文件
ofs.write(&packed[0],packed.size());//将压缩后的数据写入压缩包文件
ifs.close();
ofs.close();
return 0;
g++ compress.cpp bundle.cpp -o compress -lpthread
bundle库实现文件解压缩
#include <iostream>
#include <fstream>
#include <string>
#include "bundle.h"
int main(int argc,char* argv[])
if(argc < 3)
std::cout<<"argv[1]是压缩åŒ
å称"<<std::endl;
std::cout<<"argv[2]是解压åŽçš„文件å称"<<std::endl;
return -1;
std::string ifilename = argv[1];//压缩åŒ
å
std::string ofilename = argv[2];//解压åŽçš„文件å
std::ifstream ifs;
ifs.open(ifilename,std::ios::binary);
ifs.seekg(0,std::ios::end);
size_t fsize = ifs.tellg();
ifs.seekg(0,std::ios::beg);
std::string body;
body.resize(fsize);
ifs.read(&body[0],fsize);
ifs.close();
std::string unpacked = bundle::unpack(body);
std::ofstream ofs;
ofs.open(ofilename,std::ios::binary);
ofs.write(&unpacked[0],unpacked.size());
ofs.close();
return 0;
g++ uncompress.cpp bundle.cpp -o uncompress -lpthread
httplib 库
httplib 库,一个 C++11 单文件头的跨平台 HTTP/HTTPS 库。安装起来非常容易。只需包含 httplib.h 在你的代码中即可。 httplib 库实际上是用于搭建一个简单的 http
服务器或者客户端的库,这种第三方网络库,可以让我们免去搭建服务器或客户端的时间,把更多的精力投入到具体的业务处理中,提高开发效率
namespace httplib
struct MultipartFormData
std::string name;
std::string content;
std::string filename;
std::string content_type;
;
using MultipartFormDataItems = std::vector<MultipartFormData>;
struct Request
std::string method;
std::string path;
Headers headers;
std::string body;
// for server
std::string version;
Params params;
MultipartFormDataMap files;
Ranges ranges;
bool has_header(const char *key) const;
std::string get_header_value(const char *key, size_t id = 0) const;
void set_header(const char *key, const char *val);
bool has_file(const char *key) const;
MultipartFormData get_file_value(const char *key) const;
;
struct Response
std::string version;
int status = -1;
std::string reason;
Headers headers;
std::string body;
std::string location; // Redirect location
void set_header(const char *key, const char *val);
void set_content(const std::string &s, const char *content_type);
;
class Server
using Handler = std::function<void(const Request &, Response &)>;//函数指针类型
using Handlers = std::vector<std::pair<std::regex, Handler>>;//请求与处理函数映射表
std::function<TaskQueue *(void)> new_task_queue;//线程池-用于处理请求
Server &Get(const std::string &pattern, Handler handler);
Server &Post(const std::string &pattern, Handler handler);
Server &Put(const std::string &pattern, Handler handler);
Server &Patch(const std::string &pattern, Handler handler);
Server &Delete(const std::string &pattern, Handler handler);
Server &Options(const std::string &pattern, Handler handler);
bool listen(const char *host, int port, int socket_flags = 0);
;
class Client
Client(const std::string &host, int port);
Result Get(const char *path, const Headers &headers);
Result Post(const char *path, const char *body, size_t content_length,
const char *content_type);
Result Post(const char *path, const MultipartFormDataItems &items);
- handler:函数指针类型,定义了一个http请求处理回调函数格式。httplib搭建的服务器收到请求后,进行解析,得到一个Request结构体其中包含了请求数据,根据请求数据就可以处理请求,这个处理函数定义的格式就是Handler格式
- Request参数:保存请求数据,让用户根据请求数据进行业务处理
- Response参数:需要用户在业务处理中,填充数据,最终要响应给客户端
- regex:正则表达式-用于匹配http请求资源
- httplib收到一个新建链接,则将新的客户端连接到线程池中
handlers可以理解为一张表,映射了一个客户端请求的资源路径和一个处理函数(用户自己定义的函数),当服务器收到请求解析得到Request就会根号资源路径以及请求方法到这张表中查看有没有对应的函数,如果有则调用这个函数处理请求,如果没有,则响应404
线程池中的线程工作:1、收到请求,解析请求,得到Request结构体也就是请求的数据2、在handlers映射表中根据请求信息查找处理函数
httplib 库搭建简单服务器
#include "httplib.h"
void hello(const httplib::Request &req,httplib::以上是关于云备份项目的主要内容,如果未能解决你的问题,请参考以下文章