【Linux系统编程项目】实现部分FTP功能

news/2024/7/7 19:01:33

项目功能

服务器相关

1.获取服务器文件,get 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;
}

结束

如有问题,欢迎提出,共同进步


http://lihuaxi.xjx100.cn/news/1463744.html

相关文章

Android内存泄露

在Android中&#xff0c;内存泄漏的现象十分常见&#xff1b;而内存泄漏导致的后果会使得应用crash 定义&#xff1a;Memory Leak 指程序在申请内存后&#xff0c;当该内存不需要再使用但却无法被释放&归还给程序得现象。 内存回收策略 步骤1&#xff1a;Application Fram…

如何在window下cmd窗口执行linux指令?

1.Git&#xff1a;https://git-scm.com/downloads(官网地址) 2.根据自己的实际路径,添加两个环境变量 3.重启电脑

【python基本数据类型的时间复杂度】

时间复杂度 python基本数据类型的时间复杂度 python基本数据类型的时间复杂度 参考网站https://wiki.python.org/moin/TimeComplexity

LeetCode 88. Merge Sorted Array【数组,双指针】简单

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

【LLM评估篇】Ceval | rouge | MMLU等指标

note 一些大模型的评估模型&#xff1a;多轮&#xff1a;MTBench关注评估&#xff1a;agent bench长文本评估&#xff1a;longbench&#xff0c;longeval工具调用评估&#xff1a;toolbench安全评估&#xff1a;cvalue&#xff0c;safetyprompt等 文章目录 note常见评测benchm…

【排序】选择排序

文章目录 选择排序时间复杂度空间复杂度稳定性 代码 选择排序 以从小到大为例进行说明。 选择排序就是定义出一个最小值下标&#xff0c;然后遍历整个剩下的数组选择出最小的放进最小值下标的位置。 时间复杂度 O(N) 遍历一次即可 空间复杂度 O(1) 稳定性 不稳定 代码 p…

攻防世界-simple_php

原题 解题思路 flag被分成了两个部分&#xff1a;flag2&#xff0c;flag2。获得flag1需要满足变量a0且变量a≠0&#xff0c;这看起来不能实现&#xff0c;但实际上当变量a的值是字符时&#xff0c;与数字比较会发生强制类型转换&#xff0c;所以a为字符型数据即可&#xff0c;变…

【docker练习】

1.安装docker服务&#xff0c;配置镜像加速器 看这篇文章https://blog.csdn.net/HealerCCX/article/details/132342679?spm1001.2014.3001.5501 2.下载系统镜像&#xff08;Ubuntu、 centos&#xff09; [rootnode1 ~]# docker pull centos [rootnode1 ~]# docker pull ubu…