一个ftp客户端的实现
来源:互联网 发布:python documentation 编辑:程序博客网 时间:2024/05/17 08:15
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <termios.h>
#include <curses.h>
#include <netdb.h>
#define FTP_DEFAULT_PORT 21
#define SUCCESS 0
#define MAX_STR_LEN 64
#define MAX_BUF_LEN 4096
#define MAX_FILE_NAME 255
fd_set infds;
struct sockaddr_in ftp_server, local_host;
struct sockaddr_in Ftp_Server_ctrl_addr;
struct sockaddr_in Ftp_Server_data_addr;
int sockfd_ctrl;
int sockfd_data;
char ServerIP[MAX_STR_LEN];
int ServerPort;
char User[MAX_STR_LEN];
char Password[MAX_STR_LEN];
char MsgBuffer[MAX_BUF_LEN];
char DataBuffer[MAX_BUF_LEN];
int passive_flag = 0;
static struct termios stored_settings;
enum com_type
{
list,
put,
get
};
struct soc_set_struct
{
int soc;
enum com_type type;
int handle;
};
struct soc_set_struct soc_set[5];
int ErrorExit(constchar* error)
{
printf("Error: %s\n",error);
exit(-1);
}
int isPassive()
{
if(passive_flag ==0)
return0;
else
return1;
}
int mygetch( ) {
struct termios oldt,
newt;
int ch;
tcgetattr( STDIN_FILENO, &oldt );
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newt );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
return ch;
}
int SendControlCommand(constchar* cmd_code,constchar* cmd_para)
{
char SendBuffer[MAX_BUF_LEN];
int Length;
int SendRes;
memset(SendBuffer, 0, MAX_BUF_LEN);
if(cmd_code)
{
strcpy(SendBuffer,cmd_code);
if(cmd_para)
{
strcat(SendBuffer," ");
strcat(SendBuffer,cmd_para);
strcat(SendBuffer,"\r\n");
}
else
strcat(SendBuffer,"\r\n");
Length=strlen(SendBuffer);
SendRes = write(sockfd_ctrl,SendBuffer,Length);
}
return SendRes;
}
int GetReplyMsg(void)
{
int count;
int reply;
memset(MsgBuffer, 0, MAX_BUF_LEN);
count = read(sockfd_ctrl,MsgBuffer,MAX_BUF_LEN);
reply = atoi(MsgBuffer);
printf("[Server reply] %s", MsgBuffer);
return reply;
}
int ftp_sendcmd_re( int sock, char *cmd,void *re_buf, ssize_t *len)
{
char buf[512];
ssize_t r_len;
if ( send( sock, cmd, strlen(cmd),0 ) == -1 )
return -1;
r_len = recv( sock, buf, 512,0 );
if ( r_len <1 )return -1;
buf[r_len] = 0;
if (len !=NULL) *len = r_len;
if (re_buf !=NULL) sprintf(re_buf,"%s", buf);
return0;
}
int ftp_sendcmd( int sock,char *cmd )
{
char buf[512];
int result;
ssize_t len;
result = ftp_sendcmd_re(sock, cmd, buf, &len);
if (result ==0)
{
sscanf( buf, "%d", &result );
}
return result;
}
void GetUserAccount(void)
{
char buf[MAX_BUF_LEN];
mygetch();
printf("User:(Press Enter for anonymous):");
fgets(buf,sizeof(buf),stdin);
if(buf[0]=='\n')
strncpy(User,"anonymous",9);
else
strncpy(User,buf,strlen(buf) - 1);
// printf("User:%s\n",User);
}
void GetUserPasswd(void)
{
char buf[MAX_BUF_LEN];
printf("Password:(Press Enter for anonymous):");
char ch;
int index =0;
while(1)
{
ch = mygetch();
if(ch =='\n')
{
break;
}
buf[index] = ch;
index++;
printf("*");
}
printf("\n");
buf[index] = '\0';
if(buf[0]=='\n')
strncpy(Password,"anonymous",9);
else
strncpy(Password,buf,strlen(buf));
printf("%s",Password);
}
int FTP_Login(void) // test ok
{
GetUserAccount();
SendControlCommand("USER",User);
GetReplyMsg();
GetUserPasswd();
SendControlCommand("PASS",Password);
if(230 == GetReplyMsg())
return SUCCESS;
else
ErrorExit("can't login");
}
void GetConnectMode()
{
int choice;
printf("select passvice or assive (0 : 1)\n");
scanf("%d",&choice);
passive_flag = choice;
}
void GetServerIP(void)
{
char buf[MAX_BUF_LEN];
int choice =0;
printf("input the IP or domain name (0 : 1):");
scanf("%d",&choice);
mygetch();
if(choice ==0)
{
printf("Please input the Server's IP :");
fgets(buf,sizeof(buf),stdin);
if(buf[0]=='\n')
ErrorExit("did not input IP address!");
else
strncpy(ServerIP,buf,strlen(buf)-1);
}
else
{
printf("Please input the Server's Domain :");
fgets(buf,sizeof(buf),stdin);
struct hostent* server = gethostbyname(buf);
if(!server)
{
ErrorExit("get ip address fail\n!");
}
else
{
strcpy(ServerIP,inet_ntoa(*((struct in_addr*)server->h_addr)));
}
}
}
void GetServerPort(void)
{
char buf[MAX_BUF_LEN];
printf("Please input the Server Port:");
fgets(buf,sizeof(buf),stdin);
if(buf[0]=='\n')
ErrorExit("did not input Server's Port!");
else
ServerPort = atoi(buf);
}
void FillServerAddr(constchar* ip,unsignedshortint port,struct sockaddr_in* pServer_addr)
{
memset(pServer_addr, 0,sizeof(struct sockaddr_in));
pServer_addr->sin_family = AF_INET;
pServer_addr->sin_port = htons(port);
pServer_addr->sin_addr.s_addr = inet_addr(ip);
}
int rand_local_port()
{
int local_port;
srand((unsigned)time(NULL));
local_port = rand() % 40000 +1025;
return local_port;
}
int ftp_asv_connect()
{
int lsn_sock;
int client_port;
char cmd_buf[32];
struct sockaddr_in sin;
struct sockaddr_in local;
int addr_len =sizeof(struct sockaddr);
char local_ip[24];
char *ip_1, *ip_2, *ip_3, *ip_4;
int new_sock;
int set =sizeof(sin);
client_port = rand_local_port();
lsn_sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(lsn_sock == -1)
{
printf("Create the listen socket failure\n");
return -1;
}
memset((char *)&local_host,0,sizeof(sin));
local_host.sin_family = AF_INET;
local_host.sin_port = htons(client_port);
local_host.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(lsn_sock,(struct sockaddr*)&local_host,sizeof(sin)) == -1)
{
close(lsn_sock);
printf("bind to listen the socket failure\n");
return -1;
}
if(listen(lsn_sock,1) == -1)
{
close(lsn_sock);
printf("listen failure\n");
return -1;
}
if(getsockname(sockfd_ctrl,(struct sockaddr*)&local,(socklen_t *)&addr_len) <0)
{
close(lsn_sock);
printf("get the local host ip failure\n");
return -1;
}
snprintf(local_ip, sizeof(local_ip), inet_ntoa(local.sin_addr));
local_ip[strlen(local_ip)]='\0';
ip_1 = local_ip;
ip_2 = strchr(local_ip, '.');
*ip_2 = '\0';
ip_2++;
ip_3 = strchr(ip_2, '.');
*ip_3 = '\0';
ip_3++;
ip_4 = strchr(ip_3, '.');
*ip_4 = '\0';
ip_4++;
snprintf(cmd_buf, sizeof(cmd_buf),"PORT %s,%s,%s,%s,%d,%d", \
ip_1, ip_2, ip_3, ip_4, client_port >>8 &0xff, client_port&0xff);
SendControlCommand(cmd_buf,NULL);
GetReplyMsg();
return lsn_sock;
}
int CreateControlConnection()
{
/* create socket descriptor*/
sockfd_ctrl = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == sockfd_ctrl)
ErrorExit("Create socket failed!");
/* connect to the server */
if(connect(sockfd_ctrl,(struct sockaddr *)&Ftp_Server_ctrl_addr,sizeof(struct sockaddr_in)) == 0)
{
printf("Successfully connect to server:ip:%s,port:%d\n",
inet_ntoa(Ftp_Server_ctrl_addr.sin_addr) ,ntohs(Ftp_Server_ctrl_addr.sin_port));
}
else
ErrorExit("control connect failed!");
soc_set[0].soc = sockfd_ctrl;
return0;
}
int passive()
{
char PasvReply[MAX_BUF_LEN];
char* tmp;
int count, port;
SendControlCommand("PASV",NULL);
count = read(sockfd_ctrl, PasvReply, MAX_BUF_LEN);
printf("%s", PasvReply);
if(count <=0)
return0;
PasvReply[count] = '\0';
if(227 == atoi(PasvReply))
{
tmp = strrchr(PasvReply, ',');
port = atoi(tmp+1);
*tmp = '\0';
tmp = strrchr(PasvReply, ',');
port += atoi(tmp+1)*256;
return port;
}
return0;
}
int CreateDataConnection()
{
sockfd_data = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == sockfd_data)
ErrorExit("Create socket failed!");
if(connect(sockfd_data,(struct sockaddr *)&Ftp_Server_data_addr,sizeof(struct sockaddr_in)) == 0)
{
printf("Successfully connect to server:ip:%s,port:%d\n",
inet_ntoa(Ftp_Server_data_addr.sin_addr) ,ntohs(Ftp_Server_data_addr.sin_port));
}
else
ErrorExit("data connect failed!");
return0;
}
void FTP_CMD_START(void)
{
GetServerIP();
GetServerPort();
GetConnectMode();
FillServerAddr(ServerIP, ServerPort, &Ftp_Server_ctrl_addr);
CreateControlConnection();
GetReplyMsg();
FTP_Login();
}
void FTP_CMD_QUIT(void)
{
SendControlCommand("QUIT",NULL);
GetReplyMsg();
close(sockfd_ctrl);
}
void FTP_CMD_CWD(void)
{
char pathname[MAX_FILE_NAME];
char temp[MAX_FILE_NAME];
printf("Change to which directory:");
memset(pathname, 0,sizeof(pathname));
fgets(temp,sizeof(temp),stdin);
if(pathname[0]=='\n')
{
printf("please input the path name!");
return;
}
else
strncpy(pathname, temp, strlen(temp)-1);
SendControlCommand("CWD",pathname);
GetReplyMsg();
}
void FTP_CMD_LIST(void)
{
int result;
int data_soc;
int i =0;
int lis_soc;
int set =sizeof(local_host);
if(isPassive() ==0 )
{
ServerPort = passive();
if(ServerPort >0)
FillServerAddr(ServerIP, ServerPort, &Ftp_Server_data_addr);
SendControlCommand("LIST",NULL);
CreateDataConnection();
data_soc = sockfd_data;
}
else
{
lis_soc = ftp_asv_connect();
SendControlCommand("LIST",NULL);
data_soc = accept(lis_soc,(struct sockaddr * )&local_host,(socklen_t*)&set);
if(data_soc == -1)
{
printf("Sorry ,you can't use PORT mode,there is something wrong when the server connect to this\n");
return ;
}
}
for(i =0; i <5 ; ++i)
{
if(soc_set[i].soc == -1)
break;
}
if(i ==5)
{
printf("you can't connect to server more than 5\n");
close(sockfd_data);
}
soc_set[i].soc = data_soc;
soc_set[i].type = list;
}
void FTP_CMD_DOWNLOAD(void)
{
char pathname[MAX_FILE_NAME];
char filename[MAX_FILE_NAME];
char temp[MAX_FILE_NAME];
int newfd;
int res;
int Counter;
int data_soc;
int i =0;
int result;
int lis_soc;
int set =sizeof(local_host);
printf("Input file name to download:");
fgets(temp,sizeof(temp),stdin);
if(temp[0]=='\n')
{
printf("please input the file name!");
return;
}
else
strncpy(pathname, temp, strlen(temp)-1);
/* switch to Binary mode */
SendControlCommand("TYPE","I");
GetReplyMsg();
if(isPassive() ==0)
{
ServerPort = passive();
if(ServerPort >0)
FillServerAddr(ServerIP, ServerPort, &Ftp_Server_data_addr);
SendControlCommand("RETR", pathname);
CreateDataConnection();
data_soc = sockfd_data;
}
else
{
lis_soc = ftp_asv_connect();
SendControlCommand("RETR", pathname);
data_soc = accept(lis_soc,(struct sockaddr * )&local_host,(socklen_t*)&set);
if(data_soc == -1)
{
printf("Sorry ,you can't use PORT mode,there is something wrong when the server connect to this\n");
return ;
}
}
GetReplyMsg();
if(strrchr(pathname,'/') ==NULL){
newfd = open(pathname, O_WRONLY|O_CREAT,0644);
}
else{
newfd = open(strrchr(pathname,'/')+1, O_WRONLY|O_CREAT,0644);
}
if(newfd <0)
printf("Error: can't open file!");
else
{
for(i =0; i <5 ; ++i)
{
if(soc_set[i].soc == -1)
break;
}
if(i ==5)
{
printf("you can't connect to server more than 5\n");
close(sockfd_data);
}
soc_set[i].soc = data_soc;
soc_set[i].type = get;
soc_set[i].handle = newfd;
}
}
void FTP_CMD_UPLOAD(void)
{
char pathname[MAX_FILE_NAME];
char filename[MAX_FILE_NAME];
char temp[MAX_FILE_NAME];
int newfd;
int res;
int Counter;
int data_soc;
int i =0;
int result;
int lis_soc;
int set =sizeof(local_host);
printf("Input file name to upload:");
fgets(temp,sizeof(temp),stdin);
if(pathname[0]=='\n')
{
printf("please input the file name!");
return;
}
else
strncpy(pathname, temp, strlen(temp)-1);
SendControlCommand("TYPE","I");
GetReplyMsg();
if(isPassive() ==0)
{
ServerPort = passive();
if(ServerPort >0)
FillServerAddr(ServerIP, ServerPort, &Ftp_Server_data_addr);
SendControlCommand("STOR", pathname);
CreateDataConnection();
data_soc = sockfd_data;
}
else
{
lis_soc = ftp_asv_connect();
SendControlCommand("STOR", pathname);
data_soc = accept(lis_soc,(struct sockaddr * )&local_host,(socklen_t*)&set);
if(data_soc == -1)
{
printf("Sorry ,you can't use PORT mode,there is something wrong when the server connect to this\n");
return ;
}
}
GetReplyMsg();
newfd = open(pathname, O_RDONLY);
if(newfd <0)
printf("Error: can't open file!");
else
{
Counter = 0;
memset(DataBuffer, 0, MAX_BUF_LEN);
while((res=read(newfd, DataBuffer, MAX_BUF_LEN)) >0)
{
write(data_soc, DataBuffer, res);
Counter += res;
}
printf("%d bytes send\n", Counter);
close(data_soc);
}
}
void GetInputCmd(char* cmd)
{
char buf[MAX_BUF_LEN];
fgets(buf,sizeof(buf),stdin);
if(buf[0]=='\n')
strncpy(cmd,"?",1);
else
strncpy(cmd,buf,strlen(buf)-1);
}
int find_maxfd(int st)
{
int max_fd = st;
int i =0;
for(i =0; i <5; ++i)
{
if(soc_set[i].soc != -1)
{
if(soc_set[i].soc > max_fd)
max_fd = soc_set[i].soc;
}
}
return max_fd;
}
//显示帮助命令
void showhelp()
{
printf(" start: Connect to ftp server.\n");
printf(" ls: List files in current directory.\n");
printf(" cd: Change current directory.\n");
printf(" get: Get a file from server.\n");
printf(" put: Put a file onto server.\n");
printf(" quit: Goodbye and exit.\n");
}
void deal_user_cmd(char * command)
{
if(strcmp(command,"start") ==0)
{
FTP_CMD_START();
}
elseif(strcmp(command,"cd") ==0)
{
FTP_CMD_CWD();
}
elseif(strcmp(command,"ls") ==0)
{
FTP_CMD_LIST();
}
elseif(strcmp(command,"get") ==0)
{
FTP_CMD_DOWNLOAD();
}
elseif(strcmp(command,"put") ==0)
{
FTP_CMD_UPLOAD();
}
elseif(strcmp(command,"quit") ==0)
{
FTP_CMD_QUIT();
}
elseif(strcmp(command,"?") ==0)
{
showhelp();
}
}
int ftp_usr_cmd()
{
char command[40];
int i =0;
int result;
int Counter =0;
int res =0;
showhelp();
while(1)
{
memset(command,0,strlen(command));
FD_ZERO(&infds);
FD_SET(fileno(stdin),&infds); //将标准收入放入监听集合中去
for(i =0; i <5; ++i)
{
if(soc_set[i].soc != -1)
{
FD_SET(soc_set[i].soc,&infds);
}
}
int maxfd = find_maxfd(fileno(stdin));
if(select(maxfd +1,&infds,NULL,NULL,NULL) == -1)
{
printf("call the select fail\n");
return -1;
}
//查看标准输入是否会有输入发生
if(FD_ISSET(fileno(stdin),&infds))
{
GetInputCmd(command);
deal_user_cmd(command);
}
for(i =0; i <5; ++i)
{
if(soc_set[i].soc == -1)
continue;
if(FD_ISSET(soc_set[i].soc,&infds))
{
if(soc_set[i].soc == sockfd_ctrl)
GetReplyMsg();
elseif(soc_set[i].type == list)
{
printf("Recving data! please wait....\n");
result = read(soc_set[i].soc, DataBuffer, MAX_BUF_LEN);
printf("%s", DataBuffer);
close(soc_set[i].soc);
soc_set[i].soc = -1;
soc_set[i].type = -1;
}
elseif(soc_set[i].type == get)
{
Counter = 0;
memset(DataBuffer, 0, MAX_BUF_LEN);
while((res=read(soc_set[i].soc, DataBuffer, MAX_BUF_LEN)) >0)
{
write(soc_set[i].handle, DataBuffer, res);
Counter += res;
}
printf("%d bytes received\n", Counter);
close(soc_set[i].soc);
soc_set[i].soc = -1;
soc_set[i].type = -1;
}
}
}
}
}
void init_soc()
{
int i =0;
for(i =0; i <5; ++i)
soc_set[i].soc = -1;
}
//主函数里控制循环等待条件
int main()
{
init_soc();
ftp_usr_cmd();
}
- 一个ftp客户端的实现
- 一个简单的FTP客户端 实现上传下载
- Java实现一个简单的FTP客户端
- FTP客户端的实现
- c#实现的一个简单的FTP客户端
- ftp客户端的简单实现
- FTP客户端的代码实现
- 用PHP实现一个FTP客户端
- 使用c++实现一个FTP客户端(一)
- 使用c++实现一个FTP客户端(二)
- 使用c++实现一个FTP客户端(三)
- 利用org.apache.commons.net.ftp包实现一个简单的ftp客户端实用类
- 一个FTP客户端的C#代码
- 一个FTP客户端的C#代码
- 一个FTP客户端的C#代码
- 一个简易的FTP客户端软件
- 一个FTP客户端的C#代码
- 一个FTP客户端的C#代码
- android反编译
- linux下安装node.js
- BaseAdaPter的三重境界
- Android RSA加密解密功能的实现
- Java float保留两位小数或多位小数
- 一个ftp客户端的实现
- java字段与属性的区别
- 哈弗曼压缩与解压的原理及对象化实现
- java发送邮件问题
- 结构化设计方法
- 非对称加密,我终于理解了!
- 跟我玩swing之我的辅助工具
- 数据结构上机实验之二分查找
- Spring Autowire自动装配