一点多发FTP客户端设计
项目背景
FileZilla FTP Client这款软件只能手动上传文件到FTP,貌似我还没有找到定时扫描某个本地目录,然后执行定时上传的功能。最近遇到一个问题就是:在服务器上部署到很多个FTP客户端定时程序,每个FTP客户端exe可执行程序功能都是类似的,都是将本地服务器中的某个文件夹下的符合文件规则(如*.json,*.xml)文件通过FTP上传到指定FTP服务器上面的某个目录下。但是开的程序太多了,这样如果需要上传多个比如说雷达文件到多个FTP服务器上时,就会开启多个FTP推送客户端程序,这样服务器上面就产生多个exe可执行程序。 如下图所示:
这样看起来很不好,而且很难区分对应的是哪个FTP程序,为了解决这个问题,最好将FTP推送客户端做成一点多发的形式。
FTP File Upload Version1.0版
关于只上传一个FTP服务器地址的MFC程序可以参考我之前写的博客:VC++ libcurl FTP上传客户端程序
源代码我已经上传到Github和Gitee上面了,使用的C/C++库有libcurl、boost、pugixml
FTPUpload-Github地址 FTPUpload-Gitee地址 FTPUpload是一款基于MFC的FTP推送客户端程序,使用了libcurl实现FTP推送,使用pugixml实现xml配置文件的读写,还使用了Boost库用于目录规则的转换(涉及到日期的)。程序执行流程图如下图所示:
程序如下图所示:
FTP File Upload Version2.0版
在第一个版本的基础上做了另外一个版本,增加了Windows服务程序
FTP File Upload Version3.0版
功能描述:
- FTP多数据源多FTP目标源推送客户端的实现(支持一点多发):
- 1.从数据库中获取任务信息,分别获取需要上传的本地文件源的信息(包括需要扫描的本地目录、目录规则、文件规则等)以及
- FTP目的地信息(包括FTP的远程URL地址、FTP用户名、密码、远程的目录地址等)
- 2、遍历任务列表
- 3、针对每个任务,遍历文件源(可能有多个)
- 4、对于每个文件源,遍历需要上传的FTP地址(可能有多个)
- 5、针对每个文件源以及某个FTP目的信息的数据上传通道,创建一个FTP上传线程
- 6、对于单个的FTP上传线程,执行FTP上传,并将上传成功或失败的写入到数据库中,以便多次重复传输(这里要注意剔除哪些在本地目录已经不存在但是在数据库中还有上传记录的文件上传记录信息)
程序执行流程图
程序流程图如下图所示:
数据库设计
我使用的数据库是Sqlite3书库,选择它主要是因为它轻便而且无需提前安装。主要涉及到三张表:t_task任务表、t_source数据源表、t_dest即FTP目的地表,后续根据需要最好再加一张记录已经上传的文件列表信息,以防止重复上传相同的文件。这三张表的结构如下图示:
- 表1 t_task
- 表2 t_source
- 表3 t_dest
当然,可以选择Sqlite3数据库作为数据源,也可以使用xml配置文件作为数据源。
为了方便我使用的是Sqlite3数据库,简单方便,使用了CodeProject上面一个关于Windows系统下SQLite的C++封装类CppSQLite - C++ Wrapper for SQLite,基于此类简单封装了一下基于Sqlite3的操作。核心代码如下:
// FtpUploadMulti.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include "TaskDB.h"
#include "FTPUpload.h"
/**
* 功能描述:
* FTP多数据源多FTP目标源推送客户端的实现(支持一点多发):
* 1.从数据库中获取任务信息,分别获取需要上传的本地文件源的信息(包括需要扫描的本地目录、目录规则、文件规则等)以及
* FTP目的地信息(包括FTP的远程URL地址、FTP用户名、密码、远程的目录地址等)
* 2、遍历任务列表
* 3、针对每个任务,遍历文件源(可能有多个)
* 4、对于每个文件源,遍历需要上传的FTP地址(可能有多个)
* 5、针对每个文件源以及某个FTP目的信息的数据上传通道,创建一个FTP上传线程
* 6、对于单个的FTP上传线程,执行FTP上传,并将上传成功或失败的写入到数据库中,以便多次重复传输(这里要注意剔除哪些在本地目录已经不存在但是在数据库中还有上传记录的文件上传记录信息)
*/
int main()
{
// 创建数据库类对象
signal_log lg;
TaskDB taskDB(lg);
TaskItemArray taskList;
taskDB.init();
// 获取任务列表
taskList = taskDB.getTaskList();
// 遍历任务列表
// 遍历任务列表,获取文件源和FTP目的地
for (auto taskIter = taskList.begin(); taskIter != taskList.end(); taskIter++)
{
int srcId = taskIter->sourceId;
int destId = taskIter->destId;
SourceItemArray srcList;
DestItemArray destList;
// 获取源文件列表
srcList = taskDB.getSourceInfoBySId(srcId);
// 获取FTP目的地信息
destList = taskDB.getDestInfoByDId(destId);
for (auto srcIter = srcList.begin(); srcIter != srcList.end(); srcIter++)
{
SourceItem srcItem = *srcIter;
for (auto destIter = destList.begin(); destIter != destList.end(); destIter++)
{
DestItem destItem = *destIter;
// 执行FTP上传任务(此处最好做成一个线程,针对每个任务或者FTP通道开辟一个FTP上传线程)
FTPUpload ftp;
// 设置FTP本地目录、扫描的目录规则、文件规则
ftp.set_local_path(srcItem.localPath.c_str(), srcItem.folderRule.c_str(), srcItem.fileRule.c_str());
// 设置FTP服务器的远程URL地址、FTP用户名和密码
ftp.set_remote_path(destItem.ftpUrl.c_str(), destItem.ftpUser.c_str(), destItem.ftpPwd.c_str());
// 执行FTP上传
ftp.upload();
}
}
}
return 0;
}
- 关于C#获取动态的时间差函数
- SQL Server 存储过程
- ubuntu中配置hadoop
- jQuery选择器大全(48个代码片段+21幅图演示)
- C# 如何在Excel 动态生成PivotTable
- RabbitMQ入门HelloWorld(C#)(翻译)
- Centos环境下搭建Asp.NET Core环境和安装Jexus
- Linux系统Java环境安装配置
- ASP.NET Core 依赖注入
- 使用Hive SQL插入动态分区的Parquet表OOM异常分析
- 基于STS和JWT的微服务身份认证
- 小程序前端开发基础框架,可直接用于开发
- “盲”逆向:iOS 应用 Blind 寻踪
- Redis应用及安装
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 基于python实现可视化生成二维码工具
- Python word实现读取及导出代码解析
- Python项目跨域问题解决方案
- keras的load_model实现加载含有参数的自定义模型
- opencv 图像加法与图像融合的实现代码
- PHP图像处理技术实例总结【绘图、水印、验证码、图像压缩】
- python如何实现读取并显示图片(不需要图形界面)
- PHP文件操作实例总结【文件上传、下载、分页】
- Django中Aggregation聚合的基本使用方法
- ThinkPHP3.2.3框架实现执行原生SQL语句的方法示例
- PHP反射实际应用示例
- 解决Keras使用GPU资源耗尽的问题
- 如何表示python中的相对路径
- 基于Tensorflow读取MNIST数据集时网络超时的解决方式
- python中的错误如何查看