6.linux_ftp服务器

一、理论

FTP服务器

客户端:

        1. 获取服务器的文件  get xxx

        2. 展示服务器有哪些文件  ls

        3. 进入服务器某文件夹  cd xx

        4. 上传文件到服务器  put xx

        1. lls查看客户端本地文件

        2. lcd进入客户端xxx文件夹

服务器:

        初始化,创建子进程,对接,解析指令,执行指令,返回指令的结果

一个子进程负责一条链接通道

二、编程实战

ftpServer.c

#include<stdio.h>
#include<error.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include <unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>


#define		PWD     0
#define 	LS    	1
#define 	GET	    2

#define 	IFGO	3

#define		LLS  	4
#define 	LCD	    5
#define		CD	    6
#define 	QUIT	7
#define 	PUT	    8

#define 	DOFILE	9

struct Msg
{
	int type;
	char cmd[1024];
	char readbuf[128];
};

int msg_cmd(char *cmd)
{
	if(!strcmp("ls",cmd))		return LS;//字符串比较
	if(!strcmp("pwd",cmd))		return PWD;
	if(!strcmp("quit",cmd))		return QUIT;

	if(strstr(cmd,"cd")!=NULL)	return CD;//strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串
	if(strstr(cmd,"get")!=NULL)	return GET;
	if(strstr(cmd,"put")!=NULL)	return PUT;

}
char *getDir(char *cmd)//分割字符串
{
	char *p;
	p=strtok(cmd," ");
	p=strtok(NULL," ");
	return p;
}
void msg_handler(struct Msg msg,int fd)
{
	int ret;
	int f_fd;
	FILE *file;
	char *dir=NULL;
	char readbuf[128]={0};

	printf("cmd:%s\n",msg.cmd);//打印客户端的指令
	ret=msg_cmd(msg.cmd);//客户端的字符串转换成整数	
	switch(ret)
	{
		case LS:
		case PWD:
			file=popen(msg.cmd,"r");//对于服务器,直接运行,ls列出当前文件,pwd列出当前路径	
			fread(&msg.cmd,sizeof(msg.cmd),1,file);//读出执行的结果
			write(fd,&msg,sizeof(msg));//写入socket通道fd,并发送给客户端
			break;
		case CD:
			dir=getDir(msg.cmd);
			chdir(dir);	
			break;	
		case PUT:
			dir=getDir(msg.cmd);
			f_fd=open(dir,O_RDWR|O_CREAT,0666);		
			write(f_fd,&msg.readbuf,sizeof(msg.readbuf));
			close(f_fd);
			break;
		case GET:
			dir=getDir(msg.cmd);
			if(access(dir,F_OK)==-1)
			{
				strcpy(msg.cmd,"file not exists!");
				write(fd,&msg,sizeof(msg));
			}else{
				msg.type=DOFILE;
				f_fd=open(dir,O_RDWR);//打开文件
				read(f_fd,readbuf,sizeof(readbuf));//读文件
				strcpy(msg.cmd,readbuf);//拷贝文件
				close(f_fd);
				write(fd,&msg,sizeof(msg));//发文件
			}
			break;
		case QUIT:
			printf("client quit !\n");
			exit(-1);
	}
}



int main(int args,char *argv[])
{
	int s_fd;
	int c_fd;
	int n_read;
	int n_write;
	int n_bind;	

	if(args!=3)
	{
		perror("input");	
		exit(-1);
	}

	struct Msg msg;
	struct sockaddr_in s_addr;
	struct sockaddr_in c_addr;
	memset(&s_addr,0,sizeof(struct sockaddr_in));
	memset(&c_addr,0,sizeof(struct sockaddr_in));
	
	
	if((s_fd=socket(AF_INET,SOCK_STREAM,0))==-1)
	{
		perror("socket");
		exit(-1);
	}
	
	s_addr.sin_family=AF_INET;
	s_addr.sin_port=htons(atoi(argv[2]));
	inet_aton(argv[1],&s_addr.sin_addr);

	if((n_bind=bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr)))==-1)
	{
		perror("bind");
		exit(-1);
	}
	listen(s_fd,10);
	int len=sizeof(struct sockaddr_in);
	while(1)
	{
		if((c_fd=accept(s_fd,(struct sockaddr *)&c_addr,&len))==-1)
		{
			perror("accept");
			exit(-1);
		}
		printf("client connected : %s\n",inet_ntoa(c_addr.sin_addr));
		if(fork()==0)
		{
			while(1){
				memset(&msg.cmd,0,sizeof(msg.cmd));
				if((n_read=read(c_fd,&msg,sizeof(msg)))==0)
				{
					printf("client quit !\n");
					exit(-1);
				}else if(n_read>0)
				{
					msg_handler(msg,c_fd);
				}
			}
		}
	}
	return 0;
}

ftpClient.c

#include<stdio.h>
#include<error.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>

#define         PWD     0
#define         LS      1
#define         GET     2

#define         IFGO    3

#define         LLS     4
#define         LCD     5
#define         CD      6
#define         QUIT    7
#define         PUT     8

#define         DOFILE  9

struct Msg
{
        int type;
        char cmd[1024];
        char readbuf[128];
};
int msg_cmd(char *cmd)
{
	if(!strcmp("ls",cmd))		return LS;
	if(!strcmp("pwd",cmd))		return PWD;
	if(!strcmp("lls",cmd))		return LLS;
	if(!strcmp("quit",cmd))		return QUIT;	

	if(strstr(cmd,"cd")!=NULL)	return CD;
	if(strstr(cmd,"get")!=NULL)	return GET;
	if(strstr(cmd,"put")!=NULL)	return PUT;
	if(strstr(cmd,"lcd")!=NULL)	return LCD;
	
	return -1;
}
char *getDir(char *cmd)
{
	char *p;
	p=strtok(cmd," ");
	p=strtok(NULL," ");
	return p;
}
int msg_handler(struct Msg msg,int fd)
{
	int ret;
	int f_fd;
	char readbuf[128]={0};
	char *dir=NULL;

	ret=msg_cmd(msg.cmd);
	switch(ret)
	{
		case LS:
		case PWD:
		case GET:
			write(fd,&msg,sizeof(msg));//往服务器发指令,就ok
			break;
		case LLS:
			system("ls");
			break;
		case LCD:
			dir=getDir(msg.cmd);
			chdir(dir);	
			break;		
		case CD:
			write(fd,&msg,sizeof(msg));
			break;
		case PUT:
			strcpy(readbuf,msg.cmd);
			dir=getDir(readbuf);
			if(access(dir,F_OK)==-1)
			{
				printf("file not exists!\n");
			}else{
				f_fd=open(dir,O_RDWR);		
				read(f_fd,&msg.readbuf,sizeof(msg.readbuf));
				close(f_fd);
				write(fd,&msg,sizeof(msg));
			}
			break;
		case QUIT:
			strcpy(msg.cmd,"quit");
			write(fd,&msg,sizeof(msg));
			exit(-1);
	}
	return ret;
}
void msg_handler_server(struct Msg msg,int fd)
{
	struct Msg msgget;
	int n_read;
	int f_fd;
	char *dir;	

	if((n_read=read(fd,&msgget,sizeof(msgget)))==0)//读取服务器回传的数据
	{
		printf("server quit\n");
		exit(-1);
	}else if(msgget.type==DOFILE)
	{
		dir=getDir(msg.cmd);
		f_fd=open(dir,O_RDWR|O_CREAT,0600);
		write(f_fd,&msgget.cmd,sizeof(msgget.cmd));
		close(f_fd);
		putchar('>');
		fflush(stdout);
 	}else{//输出结果
		printf("------------------------------\n");
		printf("\n%s\n",msgget.cmd);
		printf("------------------------------\n");
		putchar('>');
	}
}
int main(int args,char *argv[])
{
        int c_fd;
        int n_read;
        int n_write;
    	int c_con;

	struct Msg msg;
	struct sockaddr_in c_addr;
	memset(&c_addr,0,sizeof(struct sockaddr_in));
    

	if(args!=3)
        {
                perror("input");
                exit(-1);
        }
	if((c_fd=socket(AF_INET,SOCK_STREAM,0))==-1)
	{
		perror("socket");
		exit(-1);
	}
	
	c_addr.sin_family=AF_INET;
	c_addr.sin_port=htons(atoi(argv[2]));
	inet_aton(argv[1],&c_addr.sin_addr);
	
	if((c_con=connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)))==-1){
		perror("connect");
		exit(-1);
	}
	int mark=0;
	int ret;
	while(1)
	{
		memset(&msg.cmd,0,sizeof(msg.cmd));
		if(mark==0)	printf(">");
		
		gets(msg.cmd);//获取用户不断的输入
		
		if(strlen(msg.cmd)==0)//为了让代码格式好看点
		{
			if(mark==1)
			{
				printf(">");
			}
		}
		
		mark=1;//为了让代码格式好看点
		
		ret=msg_handler(msg,c_fd);
		
		if(ret>IFGO)
		{
			putchar('>');
			fflush(stdout);
			continue;
		}
		if(ret==-1)
		{
			printf("command out\n");
			putchar('>');
			fflush(stdout);
			continue;
		}
		msg_handler_server(msg,c_fd);
	}	
	return 0;	
}

CLC@Embed_Learn:~/ftp$ gcc ftpServer.c -o s 

CLC@Embed_Learn:~/ftp$ gcc ftpClient.c -o c

CLC@Embed_Learn:~/ftp$ ./s 127.0.0.1 8888

CLC@Embed_Learn:~/ftp$ ./c 127.0.0.1 8888

支持上述指令,自行可验证

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值