使用SOCKET实现FTP的简易客户端

2015-01-17 20:00:57|?次阅读|上传:wustguangh【已有?条评论】发表评论

关键词:C/C++, 网络通信|来源:唯设编程网

18. 上传文件到FTP服务器

//上传文件到FTP服务器
int CFTP::ftp_upload( const char* localfile,const char* remotepath,const char* remotefilename,size_t buf_size )
{ 
	//进入目录	
	int err = ftp_cd(remotepath); 
	if(err){
		ftp_mkdir(remotepath); 
	}

	ftp_setpasv(); 
	//
	sprintf_s(m_cmd,"STOR %s
",remotefilename);
	err = ftp_sendcmd(m_cmd,m_resp,sizeof(m_resp)); 
	if(err)
		return -1;
	//得到返回码
	int code = get_state_code(m_resp);
	//125 Data connection already open; Transfer starting.
	//150 Open BINARY mode data connection for test.step
	if(code != 125 && code != 150)
		return -1;	

	FILE* pf = NULL;
	//二进制方式打开
	errno_t s_code = fopen_s(&pf,localfile,"rb"); 
	if(NULL==pf)
		return -1; 
	
	char* sendbuf = new char[buf_size];
	memset(sendbuf,0,buf_size);
	size_t len = 0; 
	while((len = fread(sendbuf,1,buf_size,pf))>0) 
	{ 
		err = send(m_sockdata,sendbuf,len,0); 
		if(err<0)
			return -1; 
	} 
	delete []sendbuf;
	//关闭数据传输SOCKET
	closesocket(m_sockdata); 
	fclose(pf); 

	//226 Transfer complete.
	err = recv_buf(m_resp,sizeof(m_resp)); 
	if(err || get_state_code(m_resp) != 226)
		return -1;

	return 0; 
}

这部分代码实现将本地文件上传到FTP服务器,需要注意,为了保证上传文件与本地文件一致,建议使用二进制方式打开本地文件,即使用rb作为文件打开参数。

19.  列出指定FTP目录的子目录和文件

//列出FTP服务器目录中的文件和子目录
int CFTP::ftp_list_dir( const char* remotePath,std::vector<FILE_ITEM>& vecFileList )
{
	int err = -1;
	if(err = ftp_cd(remotePath))
		return err;
	//
	ftp_setpasv();
	//
	sprintf_s(m_cmd,"LIST %s
",remotePath);
	err = ftp_sendcmd(m_cmd,m_resp,sizeof(m_resp));
	if(err)
		return err;
	//得到返回码
	int code = get_state_code(m_resp);
	//125 Data connection already open; Transfer starting.
	//150 Open ASCII mode data connection for /bin/ls.
	if(code != 125 && code != 150)
		return -1;	
	//存储文件列表返回内容
	std::string strFileList;

	int buf_size = 1024+1,recvLen = 0;
	char* recvbuf = new char[buf_size];
	memset(recvbuf,0,buf_size);

	while((recvLen = recv(m_sockdata,recvbuf,buf_size-1,0))>0){
		strFileList.append(recvbuf);
		memset(recvbuf,0,buf_size);
	}
	//删除缓存空间
	delete []recvbuf;
	//关闭数据传输SOCKET
	closesocket(m_sockdata);

	//分析文件行
	std::istringstream streamValue(strFileList);
	std::string line,tmpValue;
	while(getline(streamValue,line)){
		if(!line.empty()){
			std::istringstream streamLine(line);

			FILE_ITEM fileItem = {'F',0,""};
			//1.drwxrwxrwx:目录 -rw-rw-rw-:文件
			streamLine>>tmpValue;
			if(tmpValue.c_str()[0] == 'd' || tmpValue.c_str()[0] == 'D'){
				fileItem.type = 'D';
			}else{
				fileItem.type = 'F';
			}
			//2.文件大小
			streamLine>>tmpValue>>tmpValue>>tmpValue>>fileItem.fSize;
			//3.文件名
			streamLine>>tmpValue>>tmpValue>>tmpValue>>fileItem.fName;
			//将文件添加到列表中
			if(!fileItem.fName.empty() && fileItem.fName.c_str()[0] != '.')
				vecFileList.push_back(fileItem);
		}
	}
	return 0;
}

使用LIST命令可以列出指定FTP目录的子目录和文件,该函数将FTP服务器指定目录的子目录/文件保存在vector类型参数vecFileList中。

发表评论0条 】
网友评论(共?条评论)..
使用SOCKET实现FTP的简易客户端