[리눅스 시스템 프로그래밍 프로젝트] FTP 기능 일부 구현

프로젝트 기능

서버 관련

1. 서버 파일 가져오기, xxx 가져오기
2. 서버에 어떤 파일이 있는지 표시, ls
3. 서버 폴더 cd 입력
4. 파일을 서버에 업로드

클라이언트 관련

lls 클라이언트의 로컬 파일 보기
lcd 클라이언트의 xx 폴더 입력
lpwd 클라이언트의 현재 디렉터리 보기

프로젝트 코드

클라이언트 코드(코드가 너무 길어서 파일 분리가 힘드네요)
업로드 되었어요 필요하시면 다운받으시면 됩니다
https://download.csdn.net/download/qq_52749711/88233816

서버 코드의 일부

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

#define SERVER_IP		"127.0.0.1"	
#define SERVER_PORT		8888
#define RECV_MAX_LEN	128	
#define SEND_MAX_LEN	4096

#define LS		0
#define LL		1
#define CD		2
#define PWD     3
#define QUIT    4
#define GET		5


//………………………………省略处理命令的代码

int is_command(char *buf)
{
    
    	
	printf("buf = %s\n",buf);
	char *token = strtok(buf, " ");
	char *ptr = token;

	printf("ptr = %s\n",ptr);

	if(!strcmp(ptr,"ls")) return LS;

	if(!strcmp(ptr,"ll")) return LL;

	if(!strcmp(ptr,"pwd")) return PWD;

	if(!strcmp(ptr,"cd"))	return CD;

	if(!strcmp(ptr,"get"))	return GET;
	
	if(!strcmp(ptr,"quit")) return QUIT;

	return -1;
}

void client_handler(int client_sockfd,int client_pid)
{
    
    
	char *buffer = NULL;
	char *buffer_err = NULL;
	int i = 0;
	int cmd = 0;

	//开辟接收需要的空间
	buffer = (char *)malloc(sizeof(char) * RECV_MAX_LEN);
	if(buffer == NULL){
    
    
		printf("recv malloc fail\n");
		exit(-1);
	}

	while(1){
    
    
		memset(buffer,'\0',RECV_MAX_LEN);
		if(recv(client_sockfd, buffer, RECV_MAX_LEN, 0) > 0){
    
    

			//调试信息
			printf("from client msg:%s\n",buffer);	

			//调用函数判断是否有此命令
			if((cmd = is_command(buffer)) < 0){
    
    

				//申请错误信息空间,存放错误信息
				buffer_err = (char *)malloc(sizeof(char) * RECV_MAX_LEN + 100);
				sprintf(buffer_err,"command:\" %s \",not found\nyour try :ls ll cd get……\n",buffer);

				//发送错误信息给客户端
				send(client_sockfd, buffer_err, strlen(buffer_err), 0);

				//释放空间防止泄露
				free(buffer_err);
				buffer_err = NULL;
			}
			//处理命令函数,并如果是退出命令则break退出进程
			if(command_handler(client_sockfd,cmd) == QUIT) {
    
    
				free(buffer);
				buffer = NULL;
				close(client_sockfd);
				break;
			}
		}
	}
	printf("\nclient %d quit.\n",client_pid);
}

//主函数
int main()
{
    
    
	struct sockaddr_in server_addr;
	int sockfd;

	int client_sockfd;
	struct sockaddr_in client_address;
	socklen_t client_len = sizeof(client_address);


	int count = 0;
	//int socket(int domain, int type, int protocol);
	// 创建套接字
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0) {
    
    
		perror("server sockt runing fail\n");
		exit(EXIT_FAILURE);
	}
	//清空servoer_addr内存
	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(SERVER_PORT);
	server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);

	//绑定端口
	if ((bind(sockfd, (struct sockaddr*) &server_addr, sizeof(server_addr))) < 0) {
    
    
		perror("server bind fail\n");
		exit(EXIT_FAILURE);
	}

	//监听
	if (listen(sockfd, 10) < 0) {
    
    
		perror("监听失败");
		exit(EXIT_FAILURE);
	}

	//	int client_sockfd;
	//	struct sockaddr_in client_address;
	//	socklen_t client_len = sizeof(client_address);

	while(1){
    
    
		printf("wait client accept……\nnow client count is %d\nyou can use Ctrl+C to Stop Server\n",count++);
		client_sockfd = accept(sockfd, (struct sockaddr *)&client_address, &client_len);

		if (client_sockfd < 0) {
    
    
			perror("连接失败,联系客服解决");
		}else{
    
    
			//子进程处理客户端请求
			if(fork() == 0){
    
    
				client_handler(client_sockfd,getpid());	
				exit(0);
			}else{
    
    }
		}
	}


	return 0;
}

클라이언트 코드

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

#define SERVER_IP  		127.0.0.1     
#define SERVER_PORT    8888

#define SEND_MAX_LEN	128
#define RECV_MAX_LEN	4096

//本地命令
int is_command(char *send_buf)
{
    
    

	char lcd_path[128];
	
	if(!strcmp(send_buf,"lls")){
    
    
		system("ls");
		return 1;
	}  

	if(!strcmp(send_buf,"lcd")){
    
    
		memset(lcd_path,'\0',128);
		scanf("%s",lcd_path);
		//切换当前工作路径函数
		chdir(lcd_path);
		system("pwd");
		return 1;
	}

	if(!strcmp(send_buf,"lpwd")){
    
    
		system("pwd");
		return 1;
	}
	return 0;
}

int main()
{
    
    	
	struct sockaddr_in server_address;
	int sockfd;

	int pid = getpid();
	char *send_buf = NULL;
	char *recv_buf = NULL;

	int get_filefd;				//get命令的文件标识
	int get_flag = 0;			//get命令flag
	char get_path[32]; 			//get命令文件名

	sockfd = socket(AF_INET, SOCK_STREAM, 0);

	memset(&server_address, 0, sizeof(server_address));
	server_address.sin_family = AF_INET;
	server_address.sin_port = htons(SERVER_PORT);
	server_address.sin_addr.s_addr = inet_addr("127.0.0.1");

	// connect是阻塞函数,它会等待服务器的响应
	// 返回值为0表示连接成功,-1表示连接失败
	if (connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
    
    
		perror("连接失败");
		exit(EXIT_FAILURE);
	}else{
    
    
		printf("连接成功\r\n");
		send_buf = (char *)malloc(sizeof(char)*SEND_MAX_LEN);
		recv_buf = (char *)malloc(sizeof(char)*RECV_MAX_LEN);		
		while(1){
    
    
			memset(send_buf,'\0',SEND_MAX_LEN);
			memset(recv_buf,'\0',RECV_MAX_LEN);

			printf("\ninput cmd:");
			scanf("%s",send_buf);

			//判断是否为本地命令
			if(is_command(send_buf) == 0){
    
    

				send(sockfd, send_buf, strlen(send_buf), 0);

				int re = recv(sockfd, recv_buf, RECV_MAX_LEN, 0);

				//printf("->%s\nre = %d\n",recv_buf,re);

				//当我输入get之后第二个参数一定是文件名,捕获文件名创建
				if(get_flag == 1){
    
    
					sprintf(get_path,"./%s",send_buf);

					printf("get_path=%s\n",get_path);
					get_filefd = open((const char *)get_path,O_CREAT|O_RDWR|O_EXCL,0666);
					if(get_filefd == -1 ){
    
    
						printf("\ncreate file fail or file exist \n");	
						get_flag = 0;
					}else{
    
    
						lseek(get_filefd,0,SEEK_SET);

						//将数据写入文件
						write(get_filefd,recv_buf,strlen(recv_buf));
						close(get_filefd);
						get_flag = 0;
					}
				}
				printf("\nmsg from server\n##################\n%s\n##################\n\n",recv_buf);

				if(!strcmp(send_buf,"get")) get_flag = 1;

				if(!strcmp(recv_buf,"quit")){
    
    
					free(send_buf);
					free(recv_buf);
					send_buf = NULL;
					recv_buf = NULL;
					break;
				}
			}//is_command
		}//while(1)
	}

	close(sockfd);
	return 0;
}

마치다

궁금한 사항이 있으시면 편하게 제기해 주시고 함께 발전해 나가시기 바랍니다.

Guess you like

Origin blog.csdn.net/qq_52749711/article/details/132368905