头文件
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
//#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <cstring>
#include <libio.h>
#include <arpa/inet.h>
using namespace std;
//数据传输模式选择
#define PORT 1
#define PASV 2
#define BUFSIZE 1024
#define DATABUFSIZE 1024*128
#define ROOTDIRLENGTH 128
#define FILENAMESIZE 12
class CFtpClient
{
public:
int cmdSocket; //控制socket
int dataSocket; //数据socket
struct sockaddr_in addr;; //服务器IP
char* hostname; //服务器名称
hostent* host; //服务器
//int curTransferMode; //当前的数据传输模式,PORT或PASV
char* buf; //控制连接所使用的缓存
char* dataBuf;//数据连接所使用的缓存
string curdir; //当前路径,结尾不应当有'\n',另外,最后一个字符可能是'/'也可能不是
char comtradeFileName[64][13];
int fileNo;
public:
CFtpClient();//构造函数
//该函数是用来连接服务器的
int connectToServer(const char* hostname, const char* serverPort ="21" );
//该函数是用来登陆服务器的
int login(char* user, char* pass);
//该函数是用来退出服务器的
void logout();
//该函数主要是用来建立数据连接的
int createDataSocket();
//下载文件
void get(string serverFile, string localFile);
//上传文件
void put(string localFile, string serverFile);
string getDestdir(char* word);//将输入指令中的路径转化为服务器绝对路径
//关闭数据连接
void closeDataSocket();
//该函数是用来查看当前目录下的文件信息
void dir(string destdir);
//该函数解析文件名
void analysisFileName(char *data);
//该函数式用来切换目录
bool cd(const char *dir);
void ascii();
bool main_open(char * address, char* user, char* pass, char * port="21");
void main_get(char * serverfile, char * localfile);
};
cpp文件
#include "FtpClient.h"
CFtpClient::CFtpClient()
{
buf = new char[BUFSIZE];
dataBuf = new char[DATABUFSIZE];
//curTransferMode = PASV;
curdir = "/";
fileNo = 0;
}
int CFtpClient::connectToServer(const char* hostname, const char* serverPort/*="21" */ )
{
cmdSocket = socket(AF_INET, SOCK_STREAM, 0);
if(cmdSocket < 0){
printf("for create socket error\n");
return -1;
}
bzero(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(serverPort));
inet_aton(hostname,&addr.sin_addr);
if(connect(cmdSocket,(struct sockaddr *)&addr,sizeof(addr)) < 0)
{
printf("for connect error\n");
return -1;
}
return 1;
}
int CFtpClient::login(char* user, char* pass)
{
memset(buf, 0, BUFSIZE);
memcpy(buf, "USER ", 5);
memcpy((char*)&buf[5], user, strlen(user));
buf[strlen(user)+5] = '\r';
buf[strlen(user)+6] = '\n';
int rval = send(cmdSocket, buf, strlen(user)+7, 0);
printf("%s",buf);
memset(buf,0,BUFSIZE);
rval = recv(cmdSocket, buf, BUFSIZE, 0);
buf[rval] = '\0';
printf("%s\n",buf);
memset(buf, 0, BUFSIZE);
memcpy(buf, "PASS ", 5);
memcpy((char*)&buf[5], pass, strlen(pass));
buf[strlen(pass)+5] = '\r';
buf[strlen(pass)+6] = '\n';
rval = send(cmdSocket, buf, strlen(pass)+7, 0);
printf("%s\n",buf);
memset(buf, 0, BUFSIZE);
rval = recv(cmdSocket, buf, BUFSIZE, 0);
buf[rval] = '\0';
printf("%s",buf);
if(rval > 0 && buf[0] == '2')
return 1;
else
return 0;
}
void CFtpClient::logout()
{
memcpy(buf, "QUIT\r\n", 6);
send(cmdSocket, buf, 6, 0);
int rval = recv(cmdSocket, buf, BUFSIZE, 0);
if(rval > 0 && buf[0] == '2')
{
close(cmdSocket);
buf[rval] = '\0';
printf("%s",buf);
}
else
{
printf("Unnormal logout!\n");
}
return;
}
/*returns:
0 -- success
1 -- create dataSocket error
2 -- connect to server error
*/
int CFtpClient::createDataSocket()
{
memcpy(buf, "PASV\r\n", 6);
int rval = send(cmdSocket, buf, 6, 0);
rval = recv(cmdSocket, buf, BUFSIZE, 0);
buf[rval] = '\0';
printf("%s",buf);
dataSocket = socket(AF_INET, SOCK_STREAM, 0);
if(dataSocket < 0)
{
printf("error occurred when creating dataSocket in fuction createDataSocket().\n");
return 1;
}
sockaddr_in dataServer;
dataServer.sin_family = AF_INET; //address family
hostent* dataHost;
char* dataHostName;
int i = 0;
while(buf[i] != '(') i++; //i points to '('
int j = i;
while(buf[j] != ')') j++; //j points to ')'
int k = j;
while(buf[k] != ',') k--;
k--;
while(buf[k] != ',') k--; //k points to the ',' between addr and port
//cout << "i = " << i << " j = " << j << " k = " << k << endl;//
dataHostName = new char[k-i];
memcpy(dataHostName, (char*)&buf[i+1], k-i-1);
dataHostName[k-i-1] = '\0';
for(i=0; i<k-i-1; i++){
if(dataHostName[i] == ',')
dataHostName[i] = '.';
}
//cout << "dataHostName == " << dataHostName << endl;//
dataHost = gethostbyname(dataHostName);
memcpy((char*)&dataServer.sin_addr, (char*)dataHost->h_addr, dataHost->h_length);
//cout << "set sin_addr OK" << endl;//
i = j;
while(buf[i] != ',') i--; //i points to the ',' between two port number now
char* cport1 = new char[i-k];
char* cport2 = new char[j-i];
memcpy(cport1, (char*)&buf[k+1], i-k-1);
cport1[i-k-1] = '\0';
memcpy(cport2, (char*)&buf[i+1], j-i-1);
cport2[j-i-1] = '\0';
//cout << "cport1 == " << cport1 << " cport2 == " << cport2 << endl;///
int iport1 = atoi(cport1);
int iport2 = atoi(cport2);
int port = 256 * iport1 + iport2;
//cout << "port == " << port << endl;///
dataServer.sin_port = htons(port);
if(connect(dataSocket, (sockaddr*)&dataServer, sizeof dataServer) < 0){
printf("connect error in processing with PASV\n" );
return 2;
}
return 0;
}
void CFtpClient::get(string serverFile, string localFile)
{
// cout << "local : " << localFile << endl;
// cout << "remote : " << serverFile << endl;
int res = createDataSocket();
if(res != 0)
{
closeDataSocket();
return;
}
int rval;
memcpy(buf, "TYPE I\r\n", 8);
rval = send(cmdSocket, buf, 8, 0);
if(rval < 0)
{
//cout << "error occurred when sending TYPE message to server" << endl;
closeDataSocket();
return;
}
rval = recv(cmdSocket, buf, BUFSIZE, 0);
buf[rval] = '\0';
printf("%s\n",buf);
int length = serverFile.length() + 6;
memcpy(buf, "RETR ", 5);
memcpy((char*)&buf[5], (char*)&serverFile[0], serverFile.length());
buf[length-1] = '\r';
buf[length] = '\n';
rval = send(cmdSocket, buf, length+1, 0);
if(rval < 0){
//cout << "error occurred when sending RETR message to server" << endl;
closeDataSocket();
return;
}
rval = recv(cmdSocket, buf, BUFSIZE, 0);
buf[rval] = '\0';
printf("%s\n",buf);
if(buf[0] == '1')
{
FILE* file = fopen((char*)&localFile[0], "w");
if(file == NULL)
{
//cout<<"file error"<<endl;
}
int pfile = fileno(file);
while((rval = read(dataSocket, dataBuf, DATABUFSIZE)) > 0){
write(pfile, dataBuf, rval);
}
closeDataSocket();
fclose(file);
rval = recv(cmdSocket, buf, BUFSIZE, 0);
buf[rval] = '\0';
printf("%s",buf);
}
else
{
//cout << "File that you want does not exist on the server." << endl;
closeDataSocket();
}
return;
}
void CFtpClient::dir(string destdir)
{
int res = createDataSocket();
if(res != 0)
{
closeDataSocket();
return;
}
int rval;
int length = 0;
if(destdir.length() > 1 && destdir[destdir.length()-1] == '/')
{
length = destdir.length() - 1;
}
else
length = destdir.length();
memcpy(buf, "LIST ", 5);
memcpy((char*)&buf[5], (char*)&destdir[0], length);
buf[length+5] = '\n';
printf("%s\n",buf);
rval = send(cmdSocket, buf, length+6, 0);
if(rval < 0)
{
//cout << "error occurred when sending LIST message to server" << endl;
closeDataSocket();
return;
}
rval = recv(cmdSocket, buf, BUFSIZE, 0);
buf[rval] = '\0';
printf("%s",buf);
if(buf[0] == '1')
{
memset(dataBuf, 0, DATABUFSIZE);
int pos = 0;
while((rval = recv(dataSocket, &dataBuf[pos], DATABUFSIZE, 0)) > 0)
{
sleep(1);
//dataBuf[rval] = '\0';
pos += rval;
}
dataBuf[pos] = '\0';
analysisFileName(dataBuf);
closeDataSocket();
rval = recv(cmdSocket, buf, BUFSIZE, 0);
buf[rval] = '\0';
printf("%s",buf);
return;
}
else
{
//cout << "the server can not get prepared for data transformation" << endl;
closeDataSocket();
return;
}
return;
}
void CFtpClient::analysisFileName(char *data)
{
char fileInfo[2048];
memset(fileInfo,0,2048);
memcpy(fileInfo,data,strlen(data) + 1);
int i = 0;
int j = 0;
printf("analysisFileName \n%s",fileInfo);
while(fileInfo[i])
{
if(fileInfo[i] == '\n' && fileInfo[i - 5] == '.')
{
memcpy(&comtradeFileName[fileNo][0],&fileInfo[i - FILENAMESIZE -1],FILENAMESIZE);
comtradeFileName[fileNo][12] = '\0';
printf("%s %d\n",comtradeFileName[fileNo],fileNo);
fileNo++;
}
i++;
}
}
bool CFtpClient::cd(const char *dir)
{
string sdir = (string)dir;
if(sdir == ".")
{
return true;
}
else if(sdir == "..")
{
if(curdir == "/")
{
//cout << "you have been in the root directory." << endl;
}
else
{
int i = curdir.length()-1;
while(curdir[i] != '/')
{
i--;
}
char * temp = new char[i+2];
memcpy(temp, (char*)&curdir[0], i+1);
temp[i+1] = '\0';
curdir = string(temp);
}
}
else
{
string destdir;
if(dir[0] == '/')
{
destdir = sdir;
}
else
{
if(curdir[curdir.length()-1] == '/')
{
char * temp = new char[curdir.length()+sdir.length()+1];
memcpy(temp,(char*)&curdir[0], curdir.length());
memcpy((char*)&temp[curdir.length()],(char*)&sdir[0], sdir.length());
temp[curdir.length()+sdir.length()+1] = '\0';
destdir = (string)temp;
}
else
{
char* temp = new char[curdir.length()+sdir.length()+2];
memcpy(temp, (char*)&curdir[0], curdir.length());
temp[curdir.length()] = '/';
memcpy((char*)&temp[curdir.length()+1], (char*)&sdir[0], sdir.length());
temp[curdir.length()+sdir.length()+1] = '\0';
destdir = (string)temp;
}
}
memset(buf, 0, BUFSIZE);
memcpy(buf, "CWD ", 4);
memcpy((char*)&buf[4], (char*)&destdir[0], destdir.length());
buf[4+destdir.length()] = '\r';
buf[5+destdir.length()] = '\n';
int rval = send(cmdSocket, buf, destdir.length()+5, 0);
memset(buf, 0, BUFSIZE);
rval = recv(cmdSocket, buf, BUFSIZE, 0);
buf[rval] = '\0';
//cout << buf;//
if(rval <= 0)
{
//cout << "error occurred when receiving message from server in cd." << endl;
return false;
}
if(buf[0] == '2')
{//the directory exists on server
printf("%s",buf);//
curdir = destdir;
return true;
}
else if(buf[0] == '5')
{//the dirctory wanted does not exist on the server
printf("%s",buf);//
return true;
}
}
return true;
}
void CFtpClient::ascii()
{
int rval;
memcpy(buf, "TYPE A\r\n", 8);
rval = send(cmdSocket, buf, 8, 0);
if(rval < 0)
{
//cout << "error occurred when sending TYPE message to server" << endl;
closeDataSocket();
return;
}
rval = recv(cmdSocket, buf, BUFSIZE, 0);
buf[rval] = '\0';
printf("%s",buf);
}
string CFtpClient::getDestdir(char* word)
{
string destdir;
string temp = string(word);
if(word[0] == '/'){
destdir = temp;
}
else if(temp.length() >= 2 && word[0] == '.' && word[1] == '/'){//case ./
int length = 0, half = 0;
if(curdir[curdir.length()-1] != '/'){
half = curdir.length();//half is the position to write the last half
length = curdir.length() + temp.length() - 1;
}
else{
half = curdir.length() - 1;
length = curdir.length() + temp.length() - 2;
}
char* cdestdir = new char[length + 1];
memcpy(cdestdir, (char*)&curdir[0], curdir.length());
memcpy((char*)&cdestdir[half], (char*)&temp[1], temp.length()-1);
cdestdir[length] = '\0';
destdir = string(cdestdir);
}
else if(temp.length() >= 3 && word[0] == '.' && //case ../
word[1] == '.' && word[2] == '/'){
if(curdir == "/"){
//cout << "you are at the root directory now." << endl;
}
else{
int length = 0, half = 0, i;
if(curdir[curdir.length()-1] != '/'){
i = curdir.length() - 1;
}
else{
i = curdir.length() - 2;
}
while(curdir[i] != '/'){
i--;
}
half = i + 1;
length = i + temp.length() - 2;
char* cdestdir = new char[length + 1];
memcpy(cdestdir, (char*)&curdir[0], curdir.length());
memcpy((char*)&cdestdir[half], (char*)&temp[3], temp.length()-2);
cdestdir[length] = '\0';
destdir = string(cdestdir);
}
}
else{
//destdir = string("**illegal");
int length = 0, half = 0;
if(curdir[curdir.length()-1] != '/'){
half = curdir.length();//half is the position to write the last half
length = curdir.length() + temp.length() + 1;
}
else{
half = curdir.length() - 1;
length = curdir.length() + temp.length();
}
char* cdestdir = new char[length + 1];
memcpy(cdestdir, (char*)&curdir[0], curdir.length());
cdestdir[half] = '/';
memcpy((char*)&cdestdir[half+1], (char*)&temp[0], temp.length());
cdestdir[length] = '\0';
destdir = string(cdestdir);
}
return destdir;
}
void CFtpClient::closeDataSocket()
{
close(dataSocket);
return;
}
bool CFtpClient::main_open(char * address,char* user, char* pass, char * port)
{
if(connectToServer(address, port) == -1)
return false;
int len = recv(cmdSocket, buf, BUFSIZE, 0);
if(len > 0 && buf[0] == '2')
{
return login(user,pass);
}
return true;
}
void CFtpClient::main_get(char * serverfile, char * localfile)
{
string serverFile = getDestdir(serverfile);
string localFile;
int i = serverFile.length() - 1;
while(serverFile[i] != '/')
i--;
char tempdir[ROOTDIRLENGTH];
char* rootdir = getcwd(tempdir, 100);
string srootdir = (string)rootdir;
int length = serverFile.length() - i + srootdir.length() ;
localFile = (string)localfile;
//printf("%d\n",serverFile.length());
get(serverFile, localFile);
}
测试可用。