1.项目目标
- 1.ftp服务端生成气象模拟数据,数据生成周期为每分钟一份;数据包含:气温,气压,相对湿度,风向风速,降雨,能见度
- 2.数据格式:
时间:yyyy-mm-dd hh24:mi:ss
气温:单位摄氏度,小数点后一位
气压:0.1百帕,小数点后一位
相对湿度:0-100之间
风向:0-360之间
风速:单位m/s,小数点后一位
降雨量:mm,小数点后一位
能见度:单温-0.1米 - 3.数据存放的形式:以文件的形式保存生成的数据,格式如下:
站点代码,数据时间,气温,气压,相对湿度,风向,风速,降雨量,能见度 - 4.日志备份:将程序运行产生的打印输出信息备份到log日志中
- 5.crontab计划任务:让程序在后台自动运行,运行周期为1min
- 6.ftp客户端动态下载服务端产生的气象数据
2.项目前期准备
- 准备站点数据文件:
3.项目流程
流程图
1.将站点数据拷贝到LINUX平台中
2.将站点参数文件加载到容器中
== 站点数据结构==
== 代码实现==
//从站点参数文件中加到到容器中
bool LoadSTCode(const char* stcodefilename)
{
CFile file;
FILE* fp;
if(file.Open(stcodefilename,"r",true)==false)
{
//printf("File Open(%s) 失败\n",stcodefilename);
logfile.Write("File Open(%s) 失败\n",stcodefilename);
return false;
}
//fp=file.getFp();
char strbuffer[101];
CCmdStr Cmd;
struct st_code stcode;
while(true)
{
memset(&stcode,0,sizeof(stcode));
if(file.Fgets(strbuffer,100,false)==false)
{
break;
}
//printf("strbuffer=%s",strbuffer);
//字符串的拆分
Cmd.SplitToCmd(strbuffer,",",true);
Cmd.GetValue(0,stcode.province);
Cmd.GetValue(1,stcode.obtid);
Cmd.GetValue(2,stcode.cityname);
Cmd.GetValue(3,&stcode.lat);
Cmd.GetValue(4,&stcode.lon);
Cmd.GetValue(5,&stcode.height);
//printf("strbuffer=%s",strbuffer);
//printf("province=%s,obtid=%s,lat=%.2lf,lon=%.2lf,height=%.2lf\n",stcode.province,\
stcode.obtid,stcode.lat,stcode.lon,stcode.height);
vstcode.push_back(stcode);
}
return true;
}
3.设计气象数据,将生成的数据存放到容器
== 模拟的气象数据结构==
== 代码实现==
//创建全国气象站点观测数据,存放在vt_surfdata容器中
void CrtSurfData()
{
srand(time(0)); //播随机数种子
struct surfdata stsurfdata;
char strLocalTime[21];
memset(strLocalTime,0,sizeof(strLocalTime));
LocalTime(strLocalTime,"yyyy-mm-dd hh24:mi");
strcat(strLocalTime,":00");
for(int i=0;i<vstcode.size();i++)
{
memset(&stsurfdata,0,sizeof(stsurfdata));
STRCPY(stsurfdata.obtid,11,vstcode[i].obtid); //站点代码
//LocalTime(stsurfdata.datetime,"yyyy-mm-dd hh24:mi:ss",0); //数据时间采用当前时间
strncpy(stsurfdata.datetime,strLocalTime,20);
stsurfdata.t=rand()%170+200; //气温
stsurfdata.p=rand()%264+10000; //气压
stsurfdata.u=rand()%100+1; //相对湿度
stsurfdata.wd=rand()%360; //风向,0-360
stsurfdata.wf=rand()%150; //风速:单位0.1m/s
stsurfdata.r=rand()%16; //降雨量,单位:0.1mm
stsurfdata.vis=rand()%5000+10000; //能见度:0.1米
vt_surfdata.push_back(stsurfdata);
}
}
4.将测试数据写入到指定的文件中
bool CrtSurfFile(const char* surffilename)
{
CFile file;
char strLocalTime[21];
memset(strLocalTime,0,sizeof(strLocalTime));
LocalTime(strLocalTime,"yyyy-mm-dd hh24:mi:ss",0); //数据时间采用当前时间
char strFileName[301];
memset(strFileName,0,sizeof(strFileName));
snprintf(strFileName,300,"%s/SURF_ZH_%s_%d.txt",surffilename,strLocalTime,getpid());
if(file.Open(strFileName,"w")==false)
{
//printf("File.open(%s)失败!\n",strFileName);
logfile.Write("File.open(%s)失败!\n",strFileName);
return false;
}
for(int i=0;i<vt_surfdata.size();i++)
{
file.Fprintf("%s,%s,%.1f,%.1f,%d,%d,%.1f,%.1f,%.1f\n",vt_surfdata[i].obtid,vt_surfdata[i].datetime,\
vt_surfdata[i].t/10.0,vt_surfdata[i].p/10.0,vt_surfdata[i].u,vt_surfdata[i].wd,\
vt_surfdata[i].wf/10.0,vt_surfdata[i].r/10.0,vt_surfdata[i].vis/10.0);
}
//printf("生成数据文件(%s)成功!\n",strFileName);
logfile.Write("生成数据文件(%s)成功!,数据时间=%s,记录数=%d\n",strFileName,vt_surfdata[1].datetime,vt_surfdata.size());
}
5.程序运行前关闭所有的信号,并设置信号处理函数
6.设置信号退出函数
7.采用crontab实现每分钟产生一份数据
- crontab -e:编辑计划任务
8.编辑Makefile文件
9.ftp客户端动态采集服务端数据
#include "_ftp.h"
#include "_freecplus.h"
int main(int argc,char *argv[])
{
Cftp ftp;
// 登录远程FTP服务器,请改为您自己服务器的ip地址。
if (ftp.login("192.168.74.128:21","wang","1995",FTPLIB_PASSIVE) == false)
{
printf("ftp.login(192.168.74.128:21(wang/1995)) failed.\n"); return -1;
}
// 获取服务器上/home/freecplus/*.h文件列表,保存在本地的/tmp/list/tmp.list文件中。
// 如果/tmp/list目录不存在,就创建它。
if (ftp.nlist("/tmp/docs/qxidc/ftp/surfdata/*.txt","/tmp/docs/qxidc/src/ftp.txt")==false)
{ printf("ftp.nlist() failed.\n"); return -1; }
CFile File; // 采用freecplus框架的CFile类来操作list文件。
char strFileName[301];
File.Open("/tmp/docs/qxidc/src/ftp.txt","r"); // 打开list文件。
while(true) // 获取每个文件的时间和大小。
{
memset(strFileName,0,sizeof(strFileName));
if (File.Fgets(strFileName,300,true)==false) break;
printf("get %s...",strFileName);
if (ftp.get(strFileName,strFileName)==false)
{ printf("ftp.get(%s) failed.\n",strFileName); return -1; }
printf("ok.\n");
}
File.Close();
}
4.项目运行结果
1.每分钟后台自动产生一份气象数据文件
2.产生的气象数据文件内容
3.日志文件信息
4.ftp客户端动态采集(下载)数据
5.项目技术总结
- 1.c++的时间操作,文件、目录操作,日志打印,文件内容解析操作
- 2.c++vector容器的遍历,存储数据
- 3.c++类的封装,函数的封装,调用
- 4.涉及信号signal的处理,程序在后台运行时的退出
- 5.涉及makefile文件的编写以及gdb的调试
- 6.涉及crontab守护进程控制系统用户的计划任务,周期性执行事件
- 7.涉及ftp客户端动态采集服务端数据
6.完整代码展示
#include"_freecplus.h"
//黑龙江省,50136,漠河,52.97,122.52,438.5
vector<struct st_code>vstcode;//存放全国站点参数容器
bool LoadSTCode(const char* stcodefilename);//从站点参数文件中加到到容器中
struct st_code
{
char province[31];//省名称
char obtid[11]; //站点代码
char cityname[30];//城市
double lat; //纬度
double lon; //经度
double height; //海拔
};
//站点代码,数据时间,气温,气压,相对湿度,风向,风速,降雨量,能见度
//时间:yyyy-mm-dd hh24:mi:ss
//气温:单位摄氏度,小数点后一位
//相对湿度:0-100之间
//风向:0-360之间
//风速:单位m/s,小数点后一位
//降雨量:mm,小数点后一位
struct surfdata
{
char obtid[11];
char datetime[21];
int t; //气温:单位0.1摄氏度,小数点后一位
int p; //气压:0.1百帕,小数点后一位
int u; //相对湿度:0-100之间的值
int wd; //风向,0-360
int wf; //风速:单位0.1m/s
};
//创建全国气象站点观测数据,存放在vt_surfdata容器中
void CrtSurfData();
//把容器vt_surfdata中的数据写到目标文件中
bool CrtSurfFile(const char* surffilename);
vector<struct surfdata>vt_surfdata;//站点观测数据
CLogFile logfile;
//信号处理函数
void EXIT(int arg);
void CloseAllSignal();
int main(int argc,char* argv[])
{
if(argc!=4)
{
printf("本程序用于生成全国气象站点观测的分钟数据\n");
printf("/tmp/docs/qxidc/bin/crtsurfdata 站点参数 数据文件存放的目录 日志文件名\n");
return -1;
}
//关闭所有信号
CloseAllSignal();
//捕获退出信号2和15
signal(SIGINT,EXIT);
signal(SIGTERM,EXIT);
if(logfile.Open(argv[3])==false)
{
printf("打开日志(%s)文件失败\n",argv[3]);
return -1;
}
if(LoadSTCode(argv[1])==false) return -1;
//printf("加载参数文件(%s)成功!\n",argv[1]);
logfile.Write("加载参数文件(%s)成功!\n",argv[1]);
CrtSurfData();
if(CrtSurfFile(argv[2])==false) return -1;
//创建全国气象站点观测数据,存放在vt_surfdata容器中
//一分钟产生一份数据
/*while(true)
{
CrtSurfData();
//把容器中的数据写到目标文件中
if(CrtSurfFile(argv[2])==false) return -1;
sleep(60);
}*/
return 0;
}
//创建全国气象站点观测数据,存放在vt_surfdata容器中
{
srand(time(0)); //播随机数种子
struct surfdata stsurfdata;
char strLocalTime[21];
memset(strLocalTime,0,sizeof(strLocalTime));
LocalTime(strLocalTime,"yyyy-mm-dd hh24:mi");
strcat(strLocalTime,":00");
for(int i=0;i<vstcode.size();i++)
{
memset(&stsurfdata,0,sizeof(stsurfdata));
STRCPY(stsurfdata.obtid,11,vstcode[i].obtid); //站点代码
//LocalTime(stsurfdata.datetime,"yyyy-mm-dd hh24:mi:ss",0); //数据时间采用当前时间
strncpy(stsurfdata.datetime,strLocalTime,20);
stsurfdata.t=rand()%170+200; //气温
stsurfdata.p=rand()%264+10000; //气压
stsurfdata.u=rand()%100+1; //相对湿度
stsurfdata.wd=rand()%360; //风向,0-360
stsurfdata.wf=rand()%150; //风速:单位0.1m/s
stsurfdata.r=rand()%16; //降雨量,单位:0.1mm
stsurfdata.vis=rand()%5000+10000; //能见度:0.1米
vt_surfdata.push_back(stsurfdata);
}
}
//从站点参数文件中加到到容器中
bool LoadSTCode(const char* stcodefilename)
{
CFile file;
FILE* fp;
if(file.Open(stcodefilename,"r",true)==false)
{
//printf("File Open(%s) 失败\n",stcodefilename);
logfile.Write("File Open(%s) 失败\n",stcodefilename);
return false;
}
//fp=file.getFp();
char strbuffer[101];
CCmdStr Cmd;
struct st_code stcode;
while(true)
{
memset(&stcode,0,sizeof(stcode));
if(file.Fgets(strbuffer,100,false)==false)
{
break;
}
//printf("strbuffer=%s",strbuffer);
//字符串的拆分
Cmd.SplitToCmd(strbuffer,",",true);
Cmd.GetValue(0,stcode.province);
Cmd.GetValue(1,stcode.obtid);
Cmd.GetValue(2,stcode.cityname);
Cmd.GetValue(3,&stcode.lat);
Cmd.GetValue(4,&stcode.lon);
Cmd.GetValue(5,&stcode.height);
//printf("strbuffer=%s",strbuffer);
//printf("province=%s,obtid=%s,lat=%.2lf,lon=%.2lf,height=%.2lf\n",stcode.province,\
stcode.obtid,stcode.lat,stcode.lon,stcode.height);
vstcode.push_back(stcode);
}
return true;
}
//把容器vt_surfdata中的数据写到目标文件中
CFile file;
char strLocalTime[21];
memset(strLocalTime,0,sizeof(strLocalTime));
LocalTime(strLocalTime,"yyyy-mm-dd hh24:mi:ss",0); //数据时间采用当前时间
char strFileName[301];
memset(strFileName,0,sizeof(strFileName));
snprintf(strFileName,300,"%s/SURF_ZH_%s_%d.txt",surffilename,strLocalTime,getpid());
if(file.Open(strFileName,"w")==false)
{
//printf("File.open(%s)失败!\n",strFileName);
logfile.Write("File.open(%s)失败!\n",strFileName);
return false;
}
for(int i=0;i<vt_surfdata.size();i++)
{
file.Fprintf("%s,%s,%.1f,%.1f,%d,%d,%.1f,%.1f,%.1f\n",vt_surfdata[i].obtid,vt_surfdata[i].datetime,\
vt_surfdata[i].t/10.0,vt_surfdata[i].p/10.0,vt_surfdata[i].u,vt_surfdata[i].wd,\
vt_surfdata[i].wf/10.0,vt_surfdata[i].r/10.0,vt_surfdata[i].vis/10.0);
}
//printf("生成数据文件(%s)成功!\n",strFileName);
logfile.Write("生成数据文件(%s)成功!,数据时间=%s,记录数=%d\n",strFileName,vt_surfdata[1].datetime,vt_surfdata.size());
return true;
}
//关闭所有的信号
void CloseAllSignal()
{
for(int i=0;i<100;i++)
{
signal(i,SIG_IGN);
close(i);
}
}
void EXIT(int arg)
{
logfile.Write("程序退出,sig=%d\n",arg);
//程序退出
exit(0);
}
客户端采集数据代码
#include "_ftp.h"
#include "_freecplus.h"
int main(int argc,char *argv[])
{
Cftp ftp;
// 登录远程FTP服务器,请改为您自己服务器的ip地址。
if (ftp.login("192.168.74.128:21","wang","1995",FTPLIB_PASSIVE) == false)
{
printf("ftp.login(192.168.74.128:21(wang/1995)) failed.\n"); return -1;
}
// 获取服务器上/home/freecplus/*.h文件列表,保存在本地的/tmp/list/tmp.list文件中。
// 如果/tmp/list目录不存在,就创建它。
if (ftp.nlist("/tmp/docs/qxidc/ftp/surfdata/*.txt","/tmp/docs/qxidc/src/ftp.txt")==false)
{ printf("ftp.nlist() failed.\n"); return -1; }
CFile File; // 采用freecplus框架的CFile类来操作list文件。
char strFileName[301];
File.Open("/tmp/docs/qxidc/src/ftp.txt","r"); // 打开list文件。
while(true) // 获取每个文件的时间和大小。
{
memset(strFileName,0,sizeof(strFileName));
if (File.Fgets(strFileName,300,true)==false) break;
printf("get %s...",strFileName);
if (ftp.get(strFileName,strFileName)==false)
{ printf("ftp.get(%s) failed.\n",strFileName); return -1; }
printf("ok.\n");
}
File.Close();
}