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

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

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

15.  删除指定FTP目录

//删除指定FTP目录
int CFTP::ftp_rmdir( const char* dir )
{ 
	sprintf_s(m_cmd,"RMD %s
",dir);
	int err = ftp_sendcmd(m_cmd,m_resp,sizeof(m_resp)); 
	if(err)
		return -1;
	//得到返回码
	int code = get_state_code(m_resp);
	//250 RMD command successful.
	if(code != 250)
		return -1;
	
	return 0; 
} 

删除FTP目录使用的命令是RMD。

16. 改变数据传输模式,并创建数据传输SOCKET

//改变数据传输模式为PASV,并创建数据传输SOCKET
int CFTP::ftp_setpasv() 
{ 
	sprintf_s(m_cmd,"PASV
"); 
	int err = ftp_sendcmd(m_cmd,m_resp,sizeof(m_resp)); 
	if(err)
		return -1;
	//得到返回码
	int code = get_state_code(m_resp);
	//227 Entering Passive Mode (127,0,0,1,32,137).
	if(code != 227)
		return -1;	

	m_sockdata = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
	unsigned int v[6]={0}; 
	union { 
		struct sockaddr sa; 
		struct sockaddr_in in; 
	} sin; 
	sscanf_s(m_resp,"%*[^(](%u,%u,%u,%u,%u,%u",&v[2],&v[3],&v[4],&v[5],&v[0],&v[1]); 
	sin.sa.sa_family = AF_INET; 
	sin.sa.sa_data[2] = v[2]; 
	sin.sa.sa_data[3] = v[3]; 
	sin.sa.sa_data[4] = v[4]; 
	sin.sa.sa_data[5] = v[5]; 
	sin.sa.sa_data[0] = v[0]; 
	sin.sa.sa_data[1] = v[1]; 

	int on =1; 
	if (setsockopt(m_sockdata,SOL_SOCKET,SO_REUSEADDR, 
		(const char*) &on,sizeof(on)) == -1) 
	{ 
		perror("setsockopt"); 
		closesocket(m_sockdata); 
		return -1; 
	} 

	struct linger lng = { 0, 0 }; 
	if (setsockopt(m_sockdata,SOL_SOCKET,SO_LINGER, 
		(const char*) &lng,sizeof(lng)) == -1) 
	{ 
		perror("setsockopt"); 
		closesocket(m_sockdata); 
		return -1; 
	} 

	err = connect(m_sockdata,(sockaddr*)&sin,sizeof(sin)); 
	if(err)
		return -1; 
	return 0; 
}

上传/下载文件需要将数据传输模式设置为PASV,这可以通过命令PASV完成,除此之外,该函数还创建了数据传输用的SOCKET,并将该SOCKET与服务器建立连接。

17. 上传目录

//上传目录
int CFTP::ftp_upload_dir( const char* localpath,const char* remotepath,size_t buf_size)
{
	//进入FTP目录
	int err = ftp_cd(remotepath);
	if(err){
		ftp_mkdir(remotepath);
	}

	WCHAR szFind[MAX_PATH] = {0};	
	//搜索条件
	USES_CONVERSION;
	wcscpy(szFind,A2W(localpath));
	wcscat(szFind,A2W("*.*"));

	WIN32_FIND_DATA FindFileData;

	HANDLE hFind = ::FindFirstFile(szFind,&FindFileData);
	if(INVALID_HANDLE_VALUE == hFind){
		std::cout<<"对应目录不存在!"<<std::endl;
		return -1;
	}

	//查找的文件
	WCHAR szFile[MAX_PATH] = {0};
	do{
		memset(szFile,0,sizeof(szFile));
		wcscpy(szFile,A2W(localpath));
		wcscat(szFile,A2W(""));
		wcscat(szFile,FindFileData.cFileName);
		//目录
		if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
			if(FindFileData.cFileName[0] != '.'){
				WCHAR szRemotePath[MAX_PATH] = {0};
				wcscpy(szRemotePath,A2W(remotepath));
				wcscat(szRemotePath,A2W("/"));
				wcscat(szRemotePath,FindFileData.cFileName);
				//上传子目录
				ftp_upload_dir(W2A(szFile),W2A(szRemotePath),buf_size);
			}
		}//文件
		else{
			ftp_upload(W2A(szFile),remotepath,W2A(FindFileData.cFileName),buf_size);
		}
	}while(FindNextFile(hFind,&FindFileData));

	//关闭文件查找句柄
	FindClose(hFind);
	return 0;
}

该方法实现将本地指定目录的内容上传到FTP指定的目录,并且使用递归方法将目录的子目录也上传到FTP服务器。Windows目录内容的便利使用的方法主要有两个:FindFirstFile和FindNextFile,FindFirstFile方法的第一个参数是WCHAR,第二个参数是WIN32_FIND_DATA类型的数据指针,存储查找结果,这个方法返回一个HANDLE类型的数据,FindNextFile则使用这个句柄作为第一个参数,第二个参数依然是WIN32_FIND_DATA类型的数据指针,保存查询结果。使用完成后,记得调用FindClose将对应句柄关闭。

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