⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zhuftp.cpp

📁 本程序为在linux下实现FTP传输文件的实现
💻 CPP
字号:
#include "zhuftp.h"//#define TESTZHUFTP #ifdef TESTZHUFTP#include <signal.h>#endif#if 1#define Dprintf printf#else#define Dprintf #endifFtpZhu::FtpZhu():FtpStatus(FTP_DISCONNECTED),CmdSocket(0),Timeout(20),lasttime(0){}FtpZhu::~FtpZhu(){	if(CmdSocket!=0)	{		close(CmdSocket);	}}/**检查是否超时.flag:更新时间标志,0查询时间,1,更新时间.返回:0超时,1正常.*/int FtpZhu::CheckTime(int flag){	time_t ctime;	if(lasttime==0 || flag==1)	{		lasttime=time(NULL);		return 1;	}	if(flag==0)	{		ctime=time(NULL);		if(ctime-lasttime>Timeout)			return 0;	}	return 1;}/**设置超时时间,单位秒,初始默认为20秒*/void FtpZhu::SetTimeout(int interval){	Timeout=interval;}/**发送FTP命令.返回:ftp服务器的返回码.参数:sockfd连接ftp的socket.    cmd发送的命令字符串.*/int FtpZhu::SendFtpCommand(int sockfd,const char*cmd){	int ret;	char val[4];	if((ret=send(sockfd,cmd,strlen(cmd),0))==-1)	{		perror("ftp send command");	}	Dprintf("CLIENT:: %s\n",cmd);	//receive data from server	memset(recvbuffer,0,sizeof(recvbuffer));	if((ret=recv(sockfd,recvbuffer,sizeof(recvbuffer),0))==-1)		perror("ftp recv command return");	Dprintf("SERVER:: %s\n",recvbuffer);	strncpy(val,recvbuffer,3);	val[3]='\0';	ret=atoi(val);	Dprintf("Ret is %d\n",ret);	return ret;}/**登录ftp服务器.ServerIp:服务器IP,如192.168.0.59uname:用户名password:密码返回:ftp服务器的返回码.*/int FtpZhu::ConnectServer(const char *ServerIp,const char*uname,const char*password){	int ret;	char ftpcmd[64];	if((CmdSocket=socket (AF_INET,SOCK_STREAM,0))<0)	{		perror("ftp socket connect");		return -1;	}	//fill struct sockaddr_in	bzero(&cmdaddr,sizeof(cmdaddr));	cmdaddr.sin_family=AF_INET;	cmdaddr.sin_port=htons(21);	cmdaddr.sin_addr.s_addr=inet_addr(ServerIp);	//try connecting	if (connect(CmdSocket,(struct sockaddr*)&cmdaddr,sizeof(cmdaddr))<0)	{		perror("connect");		return -1;	}	//接收欢迎消息	if((recv(CmdSocket,recvbuffer,sizeof(recvbuffer),0))==-1)		perror("Connect Message Failed!");	else		Dprintf("SERVER:: %s\n",recvbuffer);	sprintf(ftpcmd,"USER %s\r\n",uname);	ret=SendFtpCommand(CmdSocket,ftpcmd);	sprintf(ftpcmd,"PASS %s\r\n",password);	ret=SendFtpCommand(CmdSocket,ftpcmd);	sprintf(ftpcmd,"TYPE I\r\n");	ret=SendFtpCommand(CmdSocket,ftpcmd);	FtpStatus=FTP_CONECTED;	return 0;}/**通过Ftp获取文件.  	支持断点续传,目前尚未支持超时控制.可由外部信号中断.	remotepath:远程ftp服务器目录	localpath:本机目录	filename:要下载的文件名.	返回:0成功,-1失败.*/int FtpZhu::GetFile(const char *remotepath,const char *localpath,const char*filename){	int ret,datasocket,dataport,recvlen,filesize;	struct sockaddr_in data_addr;	char databuf[1024],cmdbuf[128],*val;	char remotename[128],localname[128],*tmpbuf;	FILE *fp;	struct stat files;	int receiveend;		//检测ftp必须连接上服务器	if(FtpStatus != FTP_CONECTED)		return -1;	//检查本地文件是否已经存在,如果不存在则创建,如果无法创建将返回错误	sprintf(localname,"%s/%s",localpath, filename);	if ((ret = stat(localname, &files)) == -1)		filesize=0;	else		filesize=files.st_size;	if((fp=fopen(localname,"a"))==NULL)	{		perror("Open local file failed!");		return -1;	}	fseek(fp,0,SEEK_END);	//获得数据端口	ret=SendFtpCommand(CmdSocket,"PASV\r\n");	if (ret != 227)	    return -1;	val=strtok(recvbuffer,",");	for(int i=0;i<4;i++)		val=strtok(NULL,",");	dataport=atoi(val);	val=strtok(NULL,")");	dataport=dataport*256+atoi(val);	//Dprintf("data port is %d\n",dataport);	if((datasocket=socket (AF_INET,SOCK_STREAM,0))<0)	{		perror("socket");		return -1;	}	//fill struct sockaddr_in	memcpy(&data_addr,&cmdaddr,sizeof(data_addr));	data_addr.sin_port=htons(dataport);	//try connecting	if (connect(datasocket,(struct sockaddr*)&data_addr,sizeof(data_addr))<0)	{		perror("dataport connect");		return -1;	}	//设置接收文件的上次下载位置	sprintf(cmdbuf,"REST %d\r\n",filesize);	ret=SendFtpCommand(CmdSocket,cmdbuf);	sprintf(remotename,"%s/%s",remotepath,filename);	sprintf(cmdbuf,"RETR %s\r\n",remotename);	ret=SendFtpCommand(CmdSocket,cmdbuf);	if(ret==150)	{ 		receiveend=0;		//检查是否收到226,如果收到则表示数据下载完成.		tmpbuf=strchr(recvbuffer,'\n');		tmpbuf++;		if(strcmp(tmpbuf,""))		{			val=strtok(tmpbuf," ");			if (!strcmp(val,"226"))				receiveend=1;					}		FtpStatus=FTP_TRANSING;		do		{				do//开始下载文件			{				recvlen=recv(datasocket,databuf,sizeof(databuf),0);				if(recvlen==-1) 				{					perror("ftp recv data return");					break;				}				else if(recvlen==0)				{					if(receiveend==1)//如果是最后的数据,则退出						goto DownloadFileEnd;					else//离开循环去检查命令端口的数据						break;				}				else				{					fwrite(databuf,1,recvlen,fp);					fflush(fp);					CheckTime(1);				}			}while(FtpStatus==FTP_TRANSING);			//等待下载文件结束			if(FtpStatus==FTP_STOPPING)				break;			if(recv(CmdSocket,recvbuffer,sizeof(recvbuffer),0)==-1)				perror("ftp recv cmd return");			Dprintf("SERVER:%s",recvbuffer);			val=strtok(recvbuffer," ");			if (!strcmp(val,"226"))				receiveend=1;			if(CheckTime(0)==0)				break;		}while(FtpStatus==FTP_TRANSING);		//用户终止下载		if(FtpStatus==FTP_STOPPING)		{			ret=SendFtpCommand(CmdSocket,"ABOR\r\n");		}	}DownloadFileEnd:	FtpStatus=FTP_CONECTED;	//关闭临时文件	fclose(fp);	shutdown(datasocket,0);	return 0;}/**上传文件,暂不支持断点续传	remotepath:远程ftp服务器目录	localpath:本机目录	filename:要上传的文件名.	返回:0成功,-1失败.*/int FtpZhu::PutFile(const char *remotepath,const char *localpath,const char*filename){	int ret,datasocket,dataport,sendlen,recvlen;	struct sockaddr_in data_addr;	char databuf[1024],cmdbuf[128],*val;	char tmpbuf[1200],*tmpptr,*thisstr,*nextstr;	char localname[128];	FILE *fp;	int fileoffset;	ftpfiledis fdis;		//检测ftp必须连接上服务器	if(FtpStatus!=FTP_CONECTED)		return -1;	//获得数据端口	ret=SendFtpCommand(CmdSocket,"PASV\r\n");	if(ret!=227) return -1;	val=strtok(recvbuffer,",");	for(int i=0;i<4;i++)		val=strtok(NULL,",");	dataport=atoi(val);	val=strtok(NULL,")");	dataport=dataport*256+atoi(val);	//Dprintf("data port is %d\n",dataport);	if((datasocket=socket (AF_INET,SOCK_STREAM,0))<0)	{		perror("socket");		return -1;	}	//fill struct sockaddr_in	memcpy(&data_addr,&cmdaddr,sizeof(data_addr));	data_addr.sin_port=htons(dataport);	//try connecting	if (connect(datasocket,(struct sockaddr*)&data_addr,sizeof(data_addr))<0)	{		perror("dataport connect");		return -1;	}	//检查本地文件是否已经存在,如果不存在则创建	sprintf(cmdbuf,"CWD %s\r\n",remotepath);	ret=SendFtpCommand(CmdSocket,cmdbuf);	//发送LIST命令获得文件列表	sprintf(cmdbuf,"LIST \r\n");	ret=SendFtpCommand(CmdSocket,cmdbuf);	//接收文件列表	memset(tmpbuf,0,sizeof(tmpbuf));	fileoffset=0;//如果找不到文件,从0开始.	do//开始下载文件		{			recvlen=recv(datasocket,databuf,sizeof(databuf),0);			if(recvlen==-1)			{				perror("ftp recv data return");				break;			}			else if(recvlen==0)			{				if(CheckTime(0)==0)					break;			}			else			{				printf("%s",databuf);				strcat(tmpbuf,databuf);				thisstr=tmpbuf;				tmpptr=strchr(tmpbuf,'\n');				while(tmpptr!=NULL)				{					*tmpptr='\0';					nextstr=(char*)(tmpptr+1);					if(strcmp(thisstr,"")!=0)					{						sscanf(thisstr,"%s%d%s%s%d%s%d%s%s",&fdis.prior,&fdis.usern,&fdis.username,&fdis.groupname							,&fdis.filesize,&fdis.date,&fdis.day,&fdis.time,&fdis.filename);						if(strcmp(fdis.filename,filename)==0)						{							fileoffset=fdis.filesize;							goto findoffset;						}					}					thisstr=nextstr;					tmpptr=strchr(thisstr,'\n');				}				//保存上次未解析完的字符串.				strcpy(tmpbuf,thisstr);			}		}while(FtpStatus==FTP_TRANSING);		findoffset:		//等待数据传送完成.	if(recv(CmdSocket,recvbuffer,sizeof(recvbuffer),0)==-1)		perror("ftp recv cmd return");	Dprintf("SERVER:%s",recvbuffer);	//val=strtok(recvbuffer," ");	shutdown(datasocket,1);	close(datasocket);		Dprintf("FILEOFFSET is %d\n",fileoffset);	//再次获得数据端口	ret=SendFtpCommand(CmdSocket,"PASV\r\n");	if(ret!=227) return -1;	val=strtok(recvbuffer,",");	for(int i=0;i<4;i++)		val=strtok(NULL,",");	dataport=atoi(val);	val=strtok(NULL,")");	dataport=dataport*256+atoi(val);	//Dprintf("data port is %d\n",dataport);	if((datasocket=socket (AF_INET,SOCK_STREAM,0))<0)	{		perror("socket");		return -1;	}	//fill struct sockaddr_in	memcpy(&data_addr,&cmdaddr,sizeof(data_addr));	data_addr.sin_port=htons(dataport);	//try connecting	if (connect(datasocket,(struct sockaddr*)&data_addr,sizeof(data_addr))<0)	{		perror("dataport connect");		return -1;	}	sprintf(localname,"%s/%s",localpath,filename);	fp=fopen(localname,"rb");	fseek(fp,fileoffset,SEEK_SET);	sprintf(cmdbuf,"REST %d\r\n",fileoffset);	ret=SendFtpCommand(CmdSocket,cmdbuf);	sprintf(cmdbuf,"STOR %s\r\n",filename);	ret=SendFtpCommand(CmdSocket,cmdbuf);	if(ret!=150) return -1;	FtpStatus=FTP_TRANSING;	while(!feof(fp) && FtpStatus==FTP_TRANSING)//开始上传文件	{		sendlen=fread(databuf,1,sizeof(databuf),fp);		if(sendlen==-1)		{			perror("ftp send data return");			break;		}		else		{			ret=send(datasocket,databuf,sendlen,0);			if(ret==-1)			{				perror("Upload file failed!");				break;			}			}	}	shutdown(datasocket,1);	close(datasocket);	if(recv(CmdSocket,recvbuffer,sizeof(recvbuffer),0)==-1)			perror("ftp recv cmd return");	Dprintf("SERVER:%s",recvbuffer);	val=strtok(recvbuffer," ");	if (!strcmp(val,"226"))		goto returnroot;	//用户终止上传	if(FtpStatus==FTP_STOPPING)	{		ret=SendFtpCommand(CmdSocket,"ABOR\r\n");		return -1;	}returnroot:	FtpStatus=FTP_CONECTED;	//关闭数据文件	fclose(fp);		//返回根目录	sprintf(cmdbuf,"CWD /\r\n",remotepath);	ret=SendFtpCommand(CmdSocket,cmdbuf);	return 0;}/**断开ftp连接.*/int FtpZhu::Disconnect(){	if(FtpStatus==FTP_TRANSING)		FtpStatus=FTP_STOPPING;	if(FtpStatus==FTP_CONECTED)	{		shutdown(CmdSocket,2);		close(CmdSocket);		FtpStatus=FTP_DISCONNECTED;	}	SendFtpCommand(CmdSocket,"QUIT\r\n");	return 0;}/**获取当前ftp状态.*/int FtpZhu::GetFtpStatus(){	return FtpStatus;}#ifdef TESTZHUFTPstatic FtpZhu fz;static void SignalHandle(int signo){	if(signo==SIGALRM)	{		Dprintf("Receive signal alarm!\n");		fz.Disconnect();	}	return ;}//测试ftpint main(){	//fz.ConnectServer("20.3.254.254","mediabus","zhu");	fz.ConnectServer("192.168.0.159","mediabus","zhu");	//signal(SIGALRM,SignalHandle);	//alarm(12);	Dprintf("Now Test Downloading Files\n");	fz.GetFile("media",".","zhu25.mpg");	sleep(3);	Dprintf("Now Test Uploading Files\n");	fz.PutFile("tmp",".","zhu25.mpg");	sleep(1);	fz.Disconnect();	return 1;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -