【C/C++】项目_1_生成测试数据txt/xml文件(crtsurfdata.cpp),ftp协议及ftp采集模块(_ftp.h,_ftp.cpp,ftpgetfiles.cpp)

Iona ·
更新时间:2024-09-21
· 751 次阅读

1.生成数据:段错误,crontab2.ftp安装:firewall3.ftp命令:get,put3.1 登录ftp服务器(必须先开启)3.2 查看/下载/上传文件3.3 windows登录ftp4.ftp应用:OpenForRename,Fgets4.1 shell语言及数据完整性4.2 C语言实现ftp下载文件 1.生成数据:段错误,crontab

\n",\ vsurfdata[ii].obtid,vsurfdata[ii].ddatetime,vsurfdata[ii].t/10.0,vsurfdata[ii].p/10.0,\ vsurfdata[ii].u,vsurfdata[ii].wd,vsurfdata[ii].wf/10.0,vsurfdata[ii].r/10.0,vsurfdata[ii].vis/10.0); } else { File.Fprintf("%s,%s,%.1f,%.1f,%d,%d,%.1f,%.1f,%.1f\n",\ vsurfdata[ii].obtid,vsurfdata[ii].ddatetime,vsurfdata[ii].t/10.0,vsurfdata[ii].p/10.0,\ vsurfdata[ii].u,vsurfdata[ii].wd,vsurfdata[ii].wf/10.0,vsurfdata[ii].r/10.0,vsurfdata[ii].vis/10.0); } } if (strcmp(datafmt,"xml")==0) File.Fprintf("\n"); //结尾加 File.CloseAndRename(); // 关闭文件 logfile.Write("生成数据文件(%s)成功,数据时间=%s,记录数=%d!\n\n",strFileName,vsurfdata[0].ddatetime,vsurfdata.size()); vstcode.clear(); vsurfdata.clear(); return true; } void EXIT(int sig) { logfile.Write("程序退出,sig=%d\n\n",sig); exit(0); }

如下生成一个xml文件里也有800多行,最后也以结尾
在这里插入图片描述

2.ftp安装:firewall

在这里插入图片描述
在这里插入图片描述
如下是主动模式
在这里插入图片描述
如下是被动模式(经常用),设置ftp高端端口即数据端口
在这里插入图片描述
Linux操作系统的用户也是ftp的用户,可以配置专用的ftp用户,专用的ftp用户只能用于ftp,不能登录操作系统。如下是ftp安装:
安装ftp客户端:yum -y install ftp (remove)(只要ftp服务端安装并配置好防火墙等,任何主机安装了客户端都可以连上)。
安装ftp服务端:yum -y install vsftpd (本地和远程服务器都可安装)。如下是ftp服务端配置:
1.防火墙开启 21 端口和5500-6000端口
如果采用被动模式,防火墙开通21端口
(命令含义: --zone#作用域 --add-port=21/tcp#添加端口,格式为:端口/通讯协议 --permanent # 永久生效)
#firewall-cmd --zone=public --add-port=21/tcp --permanent
如果采用主动模式,防火墙还要开通20端口
#firewall-cmd --zone=public --add-port=20/tcp --permanent
#firewall-cmd --zone=public --add-port=5500-6000/tcp --permanent
(设置被动模式的高端口范围为5500-6000,passive命令为on,完成后必须init 6重启,netstat -na --ip,firewall-cmd --list-ports,防火墙配置不好可以直接关闭防火墙)
2.配置ftp高端口参数和关闭 selinux
#vi /etc/vsftpd/vsftpd.conf(必选装好vsftpd服务端,init6)

listen=YES //将上面含有listen都注释掉 listen_ipv6=NO //关闭ipv6的监听,不然会ls,dir不出命令 pam_service_name=vsftpd userlist_enable=YES tcp_wrappers=YES pasv_min_port=5500 pasv_max_port=6000 pasv_enable=YES pasv_address=47.100.167.156 //服务端公网ip

#vi /etc/selinux/config,修改成 selinux=disabled,执行 setenforce 0 使修改马上生效
在这里插入图片描述
3.登录阿里云控制台实例安全组(如上配置不成功,手动配置端口)
在这里插入图片描述
点击安全组列表中配置规则
在这里插入图片描述
4.vsftpd服务端相关操作
systemctl start vsftpd # 启动
systemctl stop vsftpd # 停止
systemctl status vsftpd # 查看
systemctl enable vsftpd # 开机自动启动vsftpd服务(类似windows下服务)
systemctl disable vsftpd # 禁用vsftpd服务
5.防火墙服务相关操作
以下是centos7的命令:
centos7中的防火墙名改成了firewall
systemctl restart firewalld.service # 重启防火墙
systemctl stop firewalld.service # 关闭防火墙
systemctl start firewalld.service # 启动防火墙
systemctl status firewalld.service # 查看防火墙服务状态
systemctl enable firewalld.service # 开机禁用防火墙
以下是centos6的命令:
chkconfig iptables off # 开机禁用防火墙
service vsftpd restart # 重启ftp服务端
service iptables stop #关闭防火墙

3.ftp命令:get,put 3.1 登录ftp服务器(必须先开启)

方法一:输入ftp ip地址,然后输入用户名和密码(adduser ,passwd )
在这里插入图片描述
方法二:输入ftp,用open连上服务器,再输入用户名和密码,如下图:
在这里插入图片描述
方法三:输入ftp -n ip地址,用user命令登录,如下图:进入ftp服务后输入open加ip地址open 118.89.50.198
在这里插入图片描述

3.2 查看/下载/上传文件

dir:显示服务器目录和文件列表
ls:显示服务器目录和文件列表
cd:进入服务器指定的目录
lcd:进入本地客户端指定的目录。lcd空可查看本地位置
(dir命令可以使用通配符“*”和“?”,比如,显示当前目录中所有扩展名为jpg的文件,可使用命令 dir *.jpg。cd命令中必须带目录名。比如 cd /tmp 表示进入/tmp目录)

ftp的传输模式分为ASCII码方式和二进制方式两种,二进制方式可以传输任何文件,包括压缩包、可执行程序、图片、视频、音频等,而ASCII码方式只能传输.txt、.htm等ascii码文件。在实际开发中,不管什么文件都用二进制方式传输文件。
type:查看当前的传输方式
ascii:设定传输方式为ASCII码方式
binary:设定传输方式为二进制方式
get/recv:下载单个文件get filename [newname](filename为下载的ftp服务器上的文件名,newname为保存在本都计算机上时使用的名字,get/recv只能取文件(文件夹需要打包压缩),加-r可以操作文件夹
在这里插入图片描述
mget:下载多个文件mget filename [filename ....](mget命令支持通配符“*”和“?”,比如:mget *.jpg 表示下载ftp服务器当前目录下的所有扩展名为jpg的文件。)
prompt:关闭/打开互交提示。关闭后,mget不用输入y

put/send:上传单个文件put filename [newname],filename为上传的本地文件名,newname为上传至ftp服务器上时使用的名字,如果不指定newname,文件将以原名上传。
mput:上传多个文件mput filename [filename …],mput命令支持通配符“*”和“?”
在这里插入图片描述
bye:结束与服务器的ftp会话并退出ftp环境
pwd:查看ftp服务器上的当前工作目录
rename filename newfilename:重命名ftp服务器上的文件
delete filename:删除ftp服务器上一个文件。
mdelete [remote-files]:删除多个文件。
mkdir pathname:在服务器上创建目录。
rmdir pathname:删除服务器上的目录。
passive:主动模式与被动模式切换。
nlist:列出服务器目录中的文件名,如:nlist /home/w /tmp/tmp.list,表示把服务器上/home/w目录下的文件列出来,结果输出到本地的/tmp/tmp.list文件中,输出文件名是全路径。
help [cmd]:显示ftp命令的帮助信息,cmd是命令名,如果不带参数,则显示所有ftp命令。

3.3 windows登录ftp

windows的命令提示符下有ftp客户端程序,但是不好用。 采用资源管理器,输入:ftp://服务器ip,如下图:
在这里插入图片描述
在空白的位置点鼠标右键,选择登录菜单, 输入用户名和密码登录ftp服务器界面,直接将文件拖到windows界面
在这里插入图片描述

4.ftp应用:OpenForRename,Fgets 4.1 shell语言及数据完整性

vi ftp.sh,mdelete* 将服务器上文件删掉,共享服务器不能删,取的时候有文件生成,不知道哪些文件取过或哪些没取过,所以这种方法不可行
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在一文件夹里:ls | wc 统计数据行数。服务器上一生成文件,本地虚拟机就取回来。以下用C语言实现ftp客户端,File.Open>写文件>File.close是需要时间的,写文件过程中ftp将这文件取走的话,取走的文件不完整,如果是银行数据不可行。如下有两个数据不完整不安全环节
在这里插入图片描述
第一环节供ftp用:创建文件SNPRINTF命名为.txt.tmp,读取Open文件.txt.tmp,数据写完后才会close再rename为.txt,避免文件还没Close被取走
第二环节供处理数据程序用:避免ftp没有get完被处理数据程序取走
在这里插入图片描述
下面在本地rename
在这里插入图片描述
以上就能避免中间状态文件被读取,下面修改crtsurfdata.cpp
在这里插入图片描述
sleep(20);// 停20秒方便观看
在这里插入图片描述
下面把上面封装起来,Open和Close时候就分别命名,写入File这个类中
在这里插入图片描述

4.2 C语言实现ftp下载文件

上面是解决临时文件问题,下面是C语言实现ftp下载文件。如下demo18用到_ftp.h(连着_ftp.cpp一起编译),_ftp.h又用到ftplib.h(连着ftplib.c一起编译,.h必用到其实现的.c/.cpp) 。.a就是静态库相当.c/.cpp一个别名,编译时不让别人看见,makefile中libftp.a就是ftplib.cftplib.h和ftplib.c源代码链接:https://pan.baidu.com/s/1P_GTtiOpMnO3KqU6_VVnzQ 提取码:u77a

CC=g++ FLAG=-g #FLAG=-02 all:crtsurfdata libftp.a demo18 ftpgetfiles libftp.a:ftplib.c gcc -c -o libftp.a ftplib.c demo18:demo18.cpp _ftp.h _ftp.cpp libftp.a g++ $(FLAGS) -o demo18 demo18.cpp _public.cpp _ftp.cpp libftp.a ftpgetfiles:ftpgetfiles.cpp _ftp.h _ftp.cpp libftp.a $(CC) $(FLAG) -o ftpgetfiles ftpgetfiles.cpp _public.cpp _ftp.cpp libftp.a cp ftpgetfiles ../bin/. crtsurfdata:crtsurfdata.cpp _public.h _public.cpp $(CC) $(FLAG) -o crtsurfdata crtsurfdata.cpp _public.cpp cp crtsurfdata ../bin/. clean: rm -rf crtsurfdata demo18 ftpgetfiles libftp // 本程序演示Cftp客户端类,采用ftp协议从服务器上获取文件,demo18 #include "_ftp.h" int main(int argc,char *argv[]) { Cftp ftp; // 登录远程FTP服务器 if (ftp.login("193.112.16.23:21","用户名","密码",FTPLIB_PASSIVE) == false) { printf("ftp.login() failed.\n"); return -1; } ftp.mtime("/home/y/surfdata/SURF_ZH_20200209122402_2815.txt"); ftp.size("/home/y/surfdata/SURF_ZH_20200209122402_2815.txt"); printf("=%s=\n",ftp.response()); // 改变本地目录 chdir("/tmp"); // 进入ftp服务器上文件存放的目录 if (ftp.chdir("/home/y/surfdata") == false) { printf("ftp.chdir() failed.\n"); return -1; } // 获取对方目录文件的列表,存放在"/tmp/ftp.list"文件中 if (ftp.nlist("*.txt","/tmp/ftp.list")== false) { printf("ftp.nlist() failed.\n"); return -1; } CFile File; File.OpenForRead("/tmp/ftp.list","r"); // 逐行读取文件的内容,并把文件get到本地 char strFileName[101]; while (true) { // 从文件中读取一行 memset(strFileName,0,sizeof(strFileName)); if (File.Fgets(strFileName,100) == false) break; strFileName[strlen(strFileName)-1]=0; //去除最后回车符 printf("get %s ...",strFileName); // 从远程取文件 if (ftp.get(strFileName,strFileName)==false) { printf("ftp.get(%s) failed.\n",strFileName); break; } printf("ok.\n"); } File.CloseAndRemove(); ftp.logout(); return 0; }

dir和nlist差不多,dir相当于ls -l。判断文件内容是否改变判断文件时间,不能判断大小
在这里插入图片描述
在这里插入图片描述

// _ftp.h #ifndef __FTP_H #define __FTP_H #include "_public.h" #include "ftplib.h" class Cftp { public: // ftp连接句柄 netbuf *m_ftpconn; // 文件的大小 unsigned int m_size; // 文件的时间modifytime char m_mtime[21]; Cftp(); ~Cftp(); // 存放login()方法登录失败的原因 bool m_connectfailed; bool m_loginfailed; bool m_optionfailed; void initdata(); // 登录ftp服务器 // in_host 服务器地址和端口,中间用":"分隔,如"192.168.1.1:21" // in_username ftp用户名 // in_password ftp的密码 // in_mode 传输模式,FTPLIB_PASSIVE是被动模式,FTPLIB_PORT是主动模式 bool login(const char *in_host,const char *in_username,const char *in_password,const int in_mode=FTPLIB_PASSIVE); // 注销 bool logout(); // 获取ftp服务器上文件的时间 bool mtime(const char *in_remotefilename); // 获取ftp服务器上文件的大小 bool size(const char *in_remotefilename); // 向服务端发送site命令 bool site(const char *in_command); // 改变ftp远程目录 bool chdir(const char *in_remotedir); // 在ftp服务器上创建目录 bool mkdir(const char *in_remotedir); // 删除ftp服务器上的目录 bool rmdir(const char *in_remotedir); // 发送list命令列出ftp服务器目录中的文件,结果保存到本地文件中 // 如果是列出当前目录,in_remotedir用"","*","."都行。 bool nlist(const char *in_remotedir,const char *out_listfilename); // 发送dir命令列出ftp服务器目录中的文件,结果保存到本地文件中 bool dir(const char *in_remotedir,const char *out_listfilename); // 从ftp服务器上获取文件 // in_remotefilename 待获取的远程文件名 // in_localfilename 本地文件名,可以与in_remotefilename不同 // bCheckMTime 文件传输完成后,是否核对文件传输前后的时间,保证文件的完整性 // 注意,文件在传输的过程中,采用临时文件命名的方法,即在in_localfilename后加".tmp",在传输 // 完成后才正式改为in_localfilename bool get(const char *in_remotefilename,const char *in_localfilename,const bool bCheckMTime=true); // 向ftp服务器发送文件 // in_localfilename 本地待发送的文件名 // in_remotefilename 远程文件名 // bCheckSize 文件传输完成后,是否核对本地和远程文件的大小,保证文件的完整性 // 注意,文件在传输的过程中,采用临时文件命名的方法,即在in_remotefilename后加".tmp",在传输 // 完成后才正式改为in_remotefilename bool put(const char *in_localfilename,const char *in_remotefilename,const bool bCheckSize=true); // 删除ftp服务器上的文件 bool ftpdelete(const char *in_remotefilename); // 把ftp服务器上的文件改名 bool ftprename(const char *in_srcremotefilename,const char *in_dstremotefilename); // 获取服务器返回信息的最后一条 return a pointer to the last response received char *response(); }; #endif

如下bool Cftp::mtime()中AddTime()在_public.cpp实现,注意"yyyymmddhh24miss"格式

// _ftp.cpp #include "_ftp.h" Cftp::Cftp() { m_ftpconn=0; initdata(); FtpInit(); m_connectfailed=false; m_loginfailed=false; m_optionfailed=false; } Cftp::~Cftp() { logout(); } void Cftp::initdata() { m_size=0; memset(m_mtime,0,sizeof(m_mtime)); } bool Cftp::login(const char *in_host,const char *in_username,const char *in_password,const int in_mode) { if (m_ftpconn != 0) { FtpQuit(m_ftpconn); m_ftpconn=0; } m_connectfailed=m_loginfailed=m_optionfailed=false; if (FtpConnect(in_host,&m_ftpconn) == false) { m_connectfailed=true; return false; } if (FtpLogin(in_username,in_password,m_ftpconn) == false) { m_loginfailed=true; return false; } if (FtpOptions(FTPLIB_CONNMODE,(long)in_mode,m_ftpconn) == false) { m_optionfailed=true; return false; } return true; } bool Cftp::logout() { if (m_ftpconn == 0) return false; FtpQuit(m_ftpconn); m_ftpconn=0; return true; } bool Cftp::get(const char *in_remotefilename,const char *in_localfilename,const bool bCheckMTime) { if (m_ftpconn == 0) return false; // 创建本地文件目录 MKDIR(in_localfilename); char strlocalfilenametmp[301]; memset(strlocalfilenametmp,0,sizeof(strlocalfilenametmp)); snprintf(strlocalfilenametmp,300,"%s.tmp",in_localfilename); // 获取远程服务器的文件的时间 if (mtime(in_remotefilename) == false) return false; // 取文件 if (FtpGet(strlocalfilenametmp,in_remotefilename,FTPLIB_IMAGE,m_ftpconn) == false) return false; // 判断文件获取前和获取后的时间,如果时间不同,表示文件已改变,返回失败 if (bCheckMTime==false) { char strmtime[21]; strcpy(strmtime,m_mtime); if (mtime(in_remotefilename) == false) return false; if (strcmp(m_mtime,strmtime) != 0) return false; } // 重置文件时间 UTime(strlocalfilenametmp,m_mtime); // 改为正式的文件 if (rename(strlocalfilenametmp,in_localfilename) != 0) return false; // 获取文件的大小 m_size=FileSize(in_localfilename); return true; } bool Cftp::mtime(const char *in_remotefilename) { if (m_ftpconn == 0) return false; memset(m_mtime,0,sizeof(m_mtime)); char strmtime[21]; memset(strmtime,0,sizeof(strmtime)); if (FtpModDate(in_remotefilename,strmtime,14,m_ftpconn) == false) return false; AddTime(strmtime,m_mtime,0+8*60*60,"yyyymmddhh24miss"); return true; } bool Cftp::size(const char *in_remotefilename) { if (m_ftpconn == 0) return false; m_size=0; if (FtpSize(in_remotefilename,&m_size,FTPLIB_IMAGE,m_ftpconn) == false) return false; return true; } bool Cftp::site(const char *in_command) { if (m_ftpconn == 0) return false; if (FtpSite(in_command,m_ftpconn) == false) return false; return true; } bool Cftp::chdir(const char *in_remotedir) { if (m_ftpconn == 0) return false; if (FtpChdir(in_remotedir,m_ftpconn) == false) return false; return true; } bool Cftp::mkdir(const char *in_remotedir) { if (m_ftpconn == 0) return false; if (FtpMkdir(in_remotedir,m_ftpconn) == false) return false; return true; } bool Cftp::rmdir(const char *in_remotedir) { if (m_ftpconn == 0) return false; if (FtpRmdir(in_remotedir,m_ftpconn) == false) return false; return true; } bool Cftp::dir(const char *in_remotedir,const char *out_listfilename) { if (m_ftpconn == 0) return false; if (FtpDir(out_listfilename,in_remotedir,m_ftpconn) == false) return false; return true; } bool Cftp::nlist(const char *in_remotedir,const char *out_listfilename) { if (m_ftpconn == 0) return false; // 创建本地文件目录 MKDIR(out_listfilename); if (FtpNlst(out_listfilename,in_remotedir,m_ftpconn) == false) return false; return true; } bool Cftp::put(const char *in_localfilename,const char *in_remotefilename,const bool bCheckSize) { if (m_ftpconn == 0) return false; char strremotefilenametmp[301]; memset(strremotefilenametmp,0,sizeof(strremotefilenametmp)); snprintf(strremotefilenametmp,300,"%s.tmp",in_remotefilename); if (FtpPut(in_localfilename,strremotefilenametmp,FTPLIB_IMAGE,m_ftpconn) == false) return false; if (FtpRename(strremotefilenametmp,in_remotefilename,m_ftpconn) == false) return false; // 判断已上传的文件的大小与本地文件是否相同,确保上传成功。 if (bCheckSize==true) { if (size(in_remotefilename) == false) return false; if (m_size != FileSize(in_localfilename)) return false; } return true; } bool Cftp::ftpdelete(const char *in_remotefilename) { if (m_ftpconn == 0) return false; if (FtpDelete(in_remotefilename,m_ftpconn) == false) return false; return true; } bool Cftp::ftprename(const char *in_srcremotefilename,const char *in_dstremotefilename) { if (m_ftpconn == 0) return false; if (FtpRename(in_srcremotefilename,in_dstremotefilename,m_ftpconn) == false) return false; return true; } char *Cftp::response() { if (m_ftpconn == 0) return 0; return FtpLastResponse(m_ftpconn); }

结构化数据:有记录有条数,操作数据库,传文件,调http接口
非结构化数据:图片,视频,word文档,ftp
(数据中心中结构化数据用操作数据库推上云,非结构化数据用ftp推上云)
在这里插入图片描述
在这里插入图片描述
下面在start.sh中
在这里插入图片描述
在这里插入图片描述
上面strbuffer[…-1]只删除linux下\n换行符效果如下,window下\r不能删除,也可能会有两个\r
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

// 从ftp服务器上采集文件,ftpgetfiles.cpp #include"_public.h" #include"_ftp.h" struct st_arg { char host[51]; int mode; char username[31]; char password[31]; char localpath[301]; char remotepath[301]; char matchname[301]; int ptype; char remotepathbak[301]; char listfilename[301]; char okfilename[301]; int timetvl; } starg; /* struct st_fileinfo { //在_public.h中定义了 char filename[301]; char mtime[21]; }; */ vector vokfilename,vokfilename1; vector vlistfile,vlistfile1; Cftp ftp; CLogFile logfile; //全局变量,日志操作类对象 //把nlist获取的文件名加载到vlistfile容器中 bool LoadListFile(); //把okfilename文件的内容加载到voklistname容器中 bool LoadOKFileName(); //比较vlistfile容器与vokfilename中的文件,得到新的两个容器 bool CompVector(); //把vokfilename1容器里的内容先写入okfilename文件中,覆盖之前的旧okfilename文件 bool WriteToOKFileName(); //ptype=1,把采集成功的文件追加到okfilename文件中 bool AppendToOKFileName(struct st_fileinfo *stfileinfo); //退出信号的处理函数 void EXIT(int sig); //本程序的业务流程的主函数 bool _ftpgetfile(); //显示文件的帮助 void _help(char *argv[]); //把xml参数读取到starg结构体中 bool _xmltoarg(char *strxmlbuffer); int main(int argc,char *argv[]) { if(argc != 3) { _help(argv); //argv是数组名也就是地址 return -1; } //关闭全部的信号和输入输出 CloseIOAndSignal(); //处理程序退出的信号 signal(SIGINT,EXIT); //中断信号 signal(SIGTERM,EXIT); //kill信号 if(logfile.Open(argv[1],"a+") == false) { logfile.Write("打开日志文件(%s)失败。\n",argv[1]); // logout会自动调用_ftp.h里析构函数,所以不用写 return -1; } if(_xmltoarg(argv[2]) == false) return -1; while(true) { if((ftp.login(starg.host,starg.username,starg.password,starg.mode)) == false) { logfile.Write("ftp.login(%s,%s,%s) failed.\n",starg.host,starg.username,starg.password); //return -1; sleep(starg.timetvl); continue; } //logfile.Write("ftp.login ok.\n"); //本程序的业务流程的主函数 _ftpgetfile(); ftp.logout(); sleep(starg.timetvl); } return 0; } //////////////////////////////////////////1.本程序的业务流程的主函数 bool _ftpgetfile() { //先chdir进入目录,这样listfilename输出就不是全路径了,节省文件大小,减小网络开销 if(ftp.chdir(starg.remotepath) == false) { logfile.Write("ftp.chdir(%s) failed.\n",starg.remotepath); return false; } //logfile.Write("chdir ok.\n"); //列出服务器目录文件 //每次取时和listfilename做对比实现增量采集 if(ftp.nlist(".",starg.listfilename) == false) { logfile.Write("ftp.nlist(%s) failed.\n",starg.remotepath); return false; } //logfile.Write("nlist ok.\n"); //把nlist获取的文件加载到vlistfile容器中,一般LoadListFile不会返回失败,但是里面有ftp.mtime联网可能会返回失败 if(LoadListFile() == false) { logfile.Write("LoadListFile failed.\n"); return -1; } //chdir(starg.localpath); //切换本地工作目录,如果这目录不存在就切换不成功,所以不用这方法,用绝对路径 if(starg.ptype == 1) { //okfilename是xml文件格式SURF_ZH_20190913131401_22226.txt20191026212900 //加载okfilename文件里的内容到容器vokfilename里 LoadOKFileName(); //把vlistfile容器中的文件与vokfilename中的文件对比,得到新的两个容器 //1.在vlistfile中存在,并已经采集成功的文件vokfilename1 //2.在vlistfile中存在,新文件(vlistfile有,vokfilename没有)或要重新采集(vlistfile与vokfilename文件时间不同)的文件vlistfile1 CompVector(); //把vokfilename1容器里的内容先写入okfilename文件中,覆盖之前的旧okfilename文件 WriteToOKFileName(); //把vlistfile1容器中的内容复制到vlistfile容器中让下面代码都可用 //vlistfile.clear(); vlistfile.swap(vlistfile1); } for(int i=0;i<vlistfile.size();i++) { char strremotefilename[301],strlocalfilename[301]; //不切换本地工作目录了,定义两个变量拼成绝对路径 SNPRINTF(strlocalfilename,300,"%s/%s",starg.localpath,vlistfile[i].filename); SNPRINTF(strremotefilename,300,"%s/%s",starg.remotepath,vlistfile[i].filename); //vlistfile为string时,vlistfile[i].c_str()。为struct时push_back进去,vlistfile[i].filename logfile.Write("get %s ...",strremotefilename); //获取文件 if(ftp.get(strremotefilename,strlocalfilename,true) == false ) { logfile.WriteEx("failed.\n"); //WriteEx不写时间 break; } logfile.WriteEx("ok.\n"); //删除文件 if (starg.ptype==2) ftp.ftpdelete(strremotefilename); //转存到备份目录 if(starg.ptype == 3) { char strremotefilenamebak[301]; //remotepathbak不要自己创建 SNPRINTF(strremotefilenamebak,300,"%s/%s",starg.remotepathbak,vlistfile[i].filename); //拼成 ftp.ftprename(strremotefilename,strremotefilenamebak); } //ptype=1,把采集成功的文件追加到okfilename文件中 if(starg.ptype == 1) { AppendToOKFileName(&vlistfile[i]); } } return true; } void EXIT(int sig) { logfile.Write("程序退出,sig=%d\n",sig); exit(0); } ///////////////////////////////////////////////2.加载对方服务器文件列表 bool LoadListFile() // 和crtsurfdata.cpp中LoadSTCode()差不多 { vlistfile.clear(); CFile file; if(file.Open(starg.listfilename,"r") == false) { logfile.Write("file.Open(%s) failed.\n",starg.listfilename); return false; } struct st_fileinfo stfileinfo; while(true) { memset(&stfileinfo,0,sizeof(stfileinfo)); if(file.Fgets(stfileinfo.filename,300,true) == false) break; //或许放在对比完下载文件的时候更合适? if(MatchFileName(stfileinfo.filename,starg.matchname) == false) continue; if(starg.ptype == 1 ) { //获取服务器文件时间 //这边可能会网络交互时返回失败,所以记日志 //只有ptype == 1才需要获取文件时间 if(ftp.mtime(stfileinfo.filename) == false) { logfile.Write("ftp.mtime(%s) failed.\n",stfileinfo.filename); return false; } strcpy(stfileinfo.mtime,ftp.m_mtime); //m_mtime在_ftp.h中AddTime,mtime成员函数中 } vlistfile.push_back(stfileinfo); //logfile.Write("vlistfile filename=%s,mtime=%s\n",stfileinfo.filename,stfileinfo.mtime); } return true; } ////////////////////////////////////////////3.加载采集成功文件列表 bool LoadOKFileName() { vokfilename.clear(); CFile file; //如果程序是第一次采集,okfilename是不存在的,并不是错误,也返回true if(file.Open(starg.okfilename,"r") == false) return true; struct st_fileinfo stfileinfo; char strbuffer[301]; while(true) { memset(&stfileinfo,0,sizeof(stfileinfo)); if(file.Fgets(strbuffer,300,true) == false) break; GetXMLBuffer(strbuffer,"filename",stfileinfo.filename,300); GetXMLBuffer(strbuffer,"mtime",stfileinfo.mtime,20); vokfilename.push_back(stfileinfo); //logfile.Write("vokfilename filename=%s,mtime=%s\n",stfileinfo.filename,stfileinfo.mtime); } return true; } //////////////////4.把vlistfile容器中的文件与vokfilename中的文件对比,得到新的两个容器 bool CompVector() { vokfilename1.clear(); vlistfile1.clear(); for(int i=0;i<vlistfile.size();i++) //这个循环得到vlistfile1 { int j=0; //在外面定义下面可以用j for(j=0;j<vokfilename.size();j++) //这个循环得到vokfilename1 { if( (strcmp(vlistfile[i].filename,vokfilename[j].filename)) == 0 && (strcmp(vlistfile[i].mtime,vokfilename[j].mtime)) == 0 ) //这两个都等的话不需要再取 { vokfilename1.push_back(vlistfile[i]); break; //不满足上面两个条件,break跳出 } } if(j == vokfilename.size()) //因为j<vokfilename.size(),所以这行意思是肯定没找到两个相等的 vlistfile1.push_back(vlistfile[i]); //if省略了{} } /* for(int i=0;i<vlistfile1.size();i++) { logfile.Write("vlistfile1 filename=%s,mtime=%s\n",vlistfile1[i].filename,vlistfile1[i].mtime); } for(int i=0;i<vokfilename1.size();i++) { logfile.Write("vokfilename1 filename=%s,mtime=%s\n",vokfilename1[i].filename,vokfilename1[i].mtime); } */ return true; } ///////////////////5.把vokfilename1容器里的内容先写入okfilename文件中,覆盖之前的旧okfilename文件 bool WriteToOKFileName() { CFile file; if(file.Open(starg.okfilename,"w") == false) { logfile.Write("file.Open(%s) failed.\n",starg.okfilename); return false; } for(int i=0;i<vokfilename1.size();i++) { file.Fprintf("%s%s\n",vokfilename1[i].filename,vokfilename1[i].mtime); } return true; } /////////////////////////6.ptype=1,把采集成功的文件追加到okfilename文件中 bool AppendToOKFileName(struct st_fileinfo *stfileinfo) { CFile file; if(file.Open(starg.okfilename,"a") == false) { logfile.Write("file.Open(%s) failed.\n",starg.okfilename); return false; } file.Fprintf("%s%s\n",stfileinfo->filename,stfileinfo->mtime); return true; } ///////////////////////////////////////7.把xml参数读取到starg结构体中 bool _xmltoarg(char *strxmlbuffer) { memset(&starg,0,sizeof(struct st_arg)); GetXMLBuffer(strxmlbuffer,"host",starg.host); if(strlen(starg.host) == 0) { logfile.Write("host is null.\n"); return false;} GetXMLBuffer(strxmlbuffer,"mode",&starg.mode); if( (starg.mode != 1) && (starg.mode != 2) ) starg.mode = 1; GetXMLBuffer(strxmlbuffer,"username",starg.username); if(strlen(starg.username) == 0) { logfile.Write("username is null.\n"); return false;} GetXMLBuffer(strxmlbuffer,"password",starg.password); if(strlen(starg.password) == 0) { logfile.Write("password is null.\n"); return false;} GetXMLBuffer(strxmlbuffer,"localpath",starg.localpath); if(strlen(starg.localpath) == 0) { logfile.Write("localpath is null.\n"); return false;} GetXMLBuffer(strxmlbuffer,"remotepath",starg.remotepath); if(strlen(starg.remotepath) == 0) { logfile.Write("remotepath is null.\n"); return false;} GetXMLBuffer(strxmlbuffer,"matchname",starg.matchname); if(strlen(starg.matchname) == 0) { logfile.Write("matchname is null.\n"); return false;} GetXMLBuffer(strxmlbuffer,"ptype",&starg.ptype); if( (starg.ptype != 1) && (starg.ptype != 2) && (starg.ptype != 3)) { logfile.Write("ptype is error.\n"); return false;} GetXMLBuffer(strxmlbuffer,"remotepathbak",starg.remotepathbak); if( (starg.ptype == 3) && (strlen(starg.remotepathbak) == 0)) { logfile.Write("remotepathbak is null.\n"); return false;} GetXMLBuffer(strxmlbuffer,"listfilename",starg.listfilename); if(strlen(starg.listfilename) == 0) { logfile.Write("listfilename is null.\n"); return false;} GetXMLBuffer(strxmlbuffer,"okfilename",starg.okfilename); if( (starg.ptype == 1) && (strlen(starg.okfilename) == 0)) { logfile.Write("okfilename is null.\n"); return false;} GetXMLBuffer(strxmlbuffer,"timetvl",&starg.timetvl); if( (starg.timetvl) == 0) { logfile.Write("timetvl is null.\n"); return false;} return true; } //显示文件的帮助 void _help(char *argv[]) { printf("\n公共模块,从ftp服务器上采集文件。\n"); printf("/root/qxidc/bin/ftpgetfile logfilename xmlbuffer \n\n"); printf("例如:/root/qxidc/bin/ftpgetfile /root/qxidc/log/ftpgetfile.log \"47.100.16.15:211y5199/root/qxidc/data/surfdata/home/yu/surfdataSURF_*.txt,*.DAT1/root/qxidc/ftplist/ftpgetfile_surfdata.list/root/qxidc/ftplist/ftpgetfile_surfdata.xml30 \"\n\n"); printf("logfilename 程序运行的日志文件名 \n"); printf("xmlbuffer 文件传输的参数,如下: \n"); printf("118.31.74.14:21 远程服务器的IP和端口 \n"); printf("1 传输模式,1-pasv(被动),2-port(主动),缺省为1 \n"); printf("gu 远程服务器的ftp用户名 \n"); printf("98 远程服务器的ftp密码 \n"); printf("/home/gu/tmp/ftpget 本地文件存放的目录 \n"); printf("/home/y/ 远程服务器文件存放的目录 \n"); printf("*.GIF 待采集文件匹配的文件名,大写匹配,"\ "不匹配的文件不会被采集,尽量精确,不允许采用*匹配全部文件\n"); printf("2 采集之后,服务器处理方式:1-什么都不做(增量采集),2-删除,3-备份 \n"); printf("/home/y/bak 远程服务器文件备份的目录,只有当ptype=3时才有效 \n"); printf("/home/gu/qxidc/list/ftpgetfile_surfdata.list 采集器列出服务器文件名的清单 \n"); printf("/home/gu/qxidc/list/ftpgetfile_surfdata.xml 已采集成功文件名清单 \n"); printf("30 采集时间间隔 单位:s 一般大于 10 \n\n"); //不能多个程序共用listfilename和okfilename }

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


作者:C-Coder



xml文件 XML c+ 模块 C++ ftp协议 测试 ftp

需要 登录 后方可回复, 如果你还没有账号请 注册新账号