网络编程项目——在线文件存储(Linux系统,C)

使用技术

  • 采用TCP/IP,文件传输需要准确无误,
  • 设置socket属性REUSE
  • 多进程实现多用户同时进行上传下载
  • 采用信号解决子进程结束回收
  • sqlit3库存储已经注册过的用户名和密码

服务器

main.c

/*===============================================================
*   文件名称:main.c
*   创 建 者:一杉方丈
*   创建日期:2023年08月30日
================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <signal.h>
#include "register.h"
#include <sys/wait.h>
void do_things(int cfd)
{
	int ret = -1;
	node msg;
	while(1){
		bzero(&msg, sizeof(msg));
		ret = read(cfd, &msg, sizeof(msg));
		if(-1 == ret){
			perror("read");
			return;
		}
		switch(msg.type){
			case 'R': 
			Region(cfd,&msg);
			break;
			case 'L':
			Login(cfd,&msg);
			break;
			case 'I':
			List(cfd,&msg);
			break;
			case 'D':
			Download(cfd,&msg);
			break;
			case 'U':
			Upload(cfd,&msg);
			break;
			case 'Q':
			Quit(cfd,&msg);
			}
	}
}

void handler(int sig)
{
	while(waitpid(-1,NULL,WNOHANG));
}

int main()
{
	int lfd, cfd;
	//解决进程回收
	signal(SIGCHLD,handler);
	//创建监听套接字
	lfd = ser_init();
	if(-1 == lfd){
		printf("->ser_init error !\n");
		return -1;
	}
	//
	while(1){
		cfd = accept(lfd,NULL,NULL);
		if(-1 == cfd){
			printf("->accept error !\n");
		}
		printf("->one client connect \n");
		pid_t pid = fork();
		if(pid == -1){
			perror("fork");
			return -1;
		}else if(pid == 0){
			close(lfd);
			do_things(cfd);
		}else{
			close(cfd);
			continue;
		}
	}
	return 0;
}

ser_init.c

/*===============================================================  
*   文件名称:ser_init.c
*   创 建 者:一杉方丈
*   创建日期:2023年08月29日
================================================================*/
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#define SER_PORT 9999
#define SIZE 1024
#ifdef PRIMSG
	#define pri(msg); printf("%s",msg);
#else
	#define pri(msg);
#endif
int ser_init()
{
	printf("->loadong......\n");
	sleep(2);
	int lfd, ret;
	lfd = socket(AF_INET,SOCK_STREAM,0);
	if(lfd == -1){
		pri("socket error");
		return -1;
	}else{
		pri("->socket      success\n");
	}
	//设置socket属性REUSE	
	int op = 1;
	ret = setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&op,sizeof(op));
	if(ret == -1){
		pri("setsockopt error\n");
		return -1;
	}else{
		pri("->setsockopt  success\n");
	}
	
	struct sockaddr_in server={
		.sin_family = AF_INET,
		.sin_port = htons(SER_PORT),
		.sin_addr.s_addr = inet_addr("0"),
	};
	
	ret = bind(lfd,(struct sockaddr*)&server,sizeof(server));
	if(ret == -1){
		pri("bind error\n");
		return -1;
	}else{
		pri("->bind        success\n");
	}

	ret = listen(lfd,SIZE);
	if(ret == -1){
		pri("listen error\n");
		return -1;
	}else{
		pri("->listen      success\n");
	}

	return lfd;
}

deal.c

/*=============================================================== 
*   文件名称:deal.c
*   创 建 者:一杉方丈
*   创建日期:2023年08月30日
================================================================*/
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include "register.h"



//-------------------------用户注册---------------------------------
void Region(int cfd, pnode usd){
	sqlite3 * db;
	int ret = sqlite3_open("my.db",&db);
	if(ret != SQLITE_OK){
		printf("open my.db fail : %s\n",sqlite3_errmsg(db));
		return;
	}
	char* errmsg;
	char** resultp;
	int nrow,ncol;
	char sql[100];
	memset(sql,0,100);
	sprintf(sql,"select * from data where name='%s'",usd->username);
	ret = sqlite3_get_table(db,sql,&resultp,&nrow,&ncol,&errmsg);
	if(ret != SQLITE_OK){
		printf("get_table my.db fail : %s\n",sqlite3_errmsg(db));
		return ;	
	}
	if(nrow != 0)
	{
		char buff[] = "->当前用户名已存在,换一个试试呢?\n";
		write(cfd,buff,strlen(buff));
		return;		
	}
	memset(sql,0,100);
	sprintf(sql,"insert into data values('%s','%s')",usd->username,usd->passwold);
	ret = sqlite3_get_table(db,sql,&resultp,&nrow,&ncol,&errmsg);
	if(ret != SQLITE_OK){
		printf("get_table my.db fail : %s\n",sqlite3_errmsg(db));
		return ;	
	}
	int i = mkdir(usd->username,0777);
	if(i == -1){
		printf("mkdir error ! \n");
		return ;
	}
	char buff[]="$>注册成功 !\n";
	write(cfd,buff,strlen(buff));
	sqlite3_close(db);
}


//--------------------------用户登录-----------------------------------
void Login(int cfd,pnode usd){
	sqlite3 * db;
	int ret = sqlite3_open("my.db",&db);
	if(ret != SQLITE_OK){
		printf("get_table my.db fail : %s\n",sqlite3_errmsg(db));
		return ;		
	}
	char* errmsg;
	char** resultp;
	int nrow,ncol;
	char sql[100];
	memset(sql,0,100);
	sprintf(sql,"select * from data where name='%s' and passwold='%s'",usd->username,usd->passwold);
	ret = sqlite3_get_table(db,sql,&resultp,&nrow,&ncol,&errmsg);
	if(ret != SQLITE_OK){
		printf("get_table my.db fail : %s\n",sqlite3_errmsg(db));
	}
	if(nrow != 1){
		char buff[] = "->账号密码错误,请重新输入\n";
		write(cfd,buff,strlen(buff));
		return ;
	}
	char buff[]="$>登陆成功 !\n";
	write(cfd,buff,strlen(buff));
	sqlite3_close(db);
}
//----------------------用户查看文件列表-------------------------------
void List(int cfd, pnode usd){
	char msg[100];
	DIR* file = opendir(usd->username);
	if(file == NULL){
		printf("->opendir error !\n");
	}
	struct dirent* ret;
	while(1)
	{
		ret=readdir(file);
		if(NULL == ret){
			break;
		}
		memset(msg,0,100);
		strcpy(msg,ret->d_name);
		char temp[] = "  ";
		write(cfd,msg,strlen(msg));
		write(cfd,temp,strlen(temp));
	}
	closedir(file);
}
//-----------------------用户下载文件----------------------------------
void Download(int cfd, pnode usd){
	char buff[100];
	char name[100];
	memset(name,0,100);
	strcpy(name,usd->username);
	char file[100];
	memset(file,0,100);
	strcpy(file,usd->passwold);
	char pathname[100] = {0};
	sprintf(pathname,"./%s/%s",name,file);
	int fd = open(pathname,O_RDONLY);
	if(fd == -1){
		printf("open error\n");
		char news[]="error";
		write(cfd,news,strlen(news));
		return;
	}
	ssize_t num;
	memset(buff,0,100);
	num = read(fd,buff,100);

//	printf("%s\n",buff);
//	printf("%d\n",(int)num);

	if( num == -1){
		printf("read error\n");
		return;
	}
	ssize_t rig;
	rig = write(cfd,buff,num);

//	printf("write:%d\n",(int)rig);

	if(rig != num)
	{
		printf("-> D write error\n");
	}
	close(fd);
}




//-----------------------用户上传文件----------------------------------
void Upload(int cfd, pnode usd){
	char buff[100] = {0};
	char name[100];
	memset(name,0,100);
	strcpy(name,usd->username);
	char file[100];
	memset(file,0,100);
	strcpy(file,usd->passwold);
	char pathname[100] = {0};
	sprintf(pathname,"./%s/%s",name,file);
	int fd = open(pathname,O_RDWR|O_CREAT,0666);
	if(fd == -1){
		printf("open | create error\n");
	}
	memset(buff,0,100);
	int num = read(cfd,buff,100);
	if(num == -1){
		printf("->UP read error !\n");
	}else{
		ssize_t rig = write(fd,buff,num);
		if(rig != num)
		{
			printf("-> U write error\n");
			return;
		}
	}
	close(fd);
}

//----------------------Quit---------------------------
void Quit(int cfd,pnode usd)
{
	printf("one client quit !\n");
}

客户端 

/*========================================================================
    > 文 件 名: client.c
    > 作    者: 一杉方丈
    > 创建时间: 2023年08月31日 星期四 09时46分05秒 
 =======================================================================*/

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

#define SIZE 128
typedef struct{
	char type;
	char username[SIZE];
	char passwold[SIZE];
}node,*pnode;

char buff[SIZE];
char name[SIZE];
void Quit(int);
void deal(int);
void List(int);
void Download(int);
void Upload(int);

int main( )
{
	node msg;
	int lfd = socket(AF_INET,SOCK_STREAM,0);
	if(lfd == -1){
		printf("socket error !\n");
		return -1;
	}
	printf("========================================\n->网盘初始化成功 ! \n");

	struct sockaddr_in server={
		.sin_family = AF_INET,
		.sin_port = htons(9999),
		.sin_addr.s_addr = inet_addr("192.168.18.115")
	};
	int ret = connect(lfd,(struct sockaddr*)&server,sizeof(server));
	if(ret == -1){
		printf("connect error !\n");
		return -1;
	}
	printf("->连接资源库成功 ! \n");
	printf("========================================\n->欢迎使用高端大气上档次网盘\n->后续操作请按照提示进行操作\n========================================\n");

AA:	printf("->是否已有账号?(有:L/无:R)\n->");
	memset(buff,0,SIZE);
	fgets(buff,SIZE,stdin);
	msg.type = buff[0];

	
	if(msg.type == 'R'){
		while(1){
		memset(buff,0,SIZE);
		printf("->请输入要创建的账号:\n->");
		fgets(buff,SIZE,stdin);
		if(buff[strlen(buff)-1] == '\n')
			buff[strlen(buff)-1] = '\0';
		strcpy(msg.username,buff);
		memset(buff,0,SIZE);
		printf("->请输入密码:\n->");
		fgets(buff,SIZE,stdin);
		if(buff[strlen(buff)-1] == '\n')
			buff[strlen(buff)-1] = '\0';
		strcpy(msg.passwold,buff);
		
		write(lfd,&msg,sizeof(msg));
		
		memset(buff,0,SIZE);
		read(lfd,buff,SIZE);
		printf("%s",buff);	
		
		if(buff[0]=='$')
			break;
		}

	}else if(msg.type == 'L')
	{
		while(1)
		{
		memset(buff,0,SIZE);
		printf("->请输入账号:\n->");
		fgets(buff,SIZE,stdin);
		if(buff[strlen(buff)-1] == '\n')
			buff[strlen(buff)-1] = '\0';
		strcpy(msg.username,buff);
		
		memset(buff,0,SIZE);
		printf("->请输入密码:\n->");
		fgets(buff,SIZE,stdin);
		if(buff[strlen(buff)-1] == '\n')
			buff[strlen(buff)-1] = '\0';
		strcpy(msg.passwold,buff);
		write(lfd,&msg,sizeof(msg));
		memset(buff,0,SIZE);
		read(lfd,buff,SIZE);
		printf("%s",buff);	
		if(buff[0]=='$'){
			break;
		}
		}
	}else{ 
		printf("->!!!请按照提示进行输入!!!\n");
		goto AA;
	}

	strcpy(name,msg.username);
	while(1){
	memset(buff,0,SIZE);
	printf("========================================\n->I:查看目录下的文件\n->D:下载文件\n->U:上传文件\n->Q:退出应用\n========================================\n->");
	fgets(buff,SIZE,stdin);
        if(strncmp(buff,"I",1) == 0){
        	List(lfd);
        }
        else if(strncmp(buff,"D",1) == 0){
        	Download(lfd);
        }
        else if(strncmp(buff,"U",1) == 0){
        	Upload(lfd);
        }
	else if(strncmp(buff,"Q",1) == 0){
		Quit(lfd);
		return 0;
	}
	}
	return 0;
}
void Quit(int lfd)
{
	node msg;
	msg.type = 'Q';
	strcpy(msg.username,name);
	write(lfd,&msg,sizeof(msg));
	printf("========================================\n->欢迎下次使用\n========================================\n");
}

void List(int lfd)
{
	node msg;
	msg.type = 'I';
	strcpy(msg.username,name);
	write(lfd,&msg,sizeof(msg));
	memset(buff,0,SIZE);
	read(lfd,buff,SIZE);
	printf("->  %s\n",buff);
}

void Download(int lfd)
{
	node msg;
	msg.type = 'D';
	strcpy(msg.username,name);
	memset(buff,0,SIZE);
	printf("->输入要下载的文件名:\n->");
	fgets(buff,SIZE,stdin);
	if(buff[strlen(buff)-1] == '\n')
		buff[strlen(buff)-1] = '\0';
	strcpy(msg.passwold,buff);
	write(lfd,&msg,sizeof(msg));
	int fd = open(buff,O_WRONLY|O_CREAT|O_TRUNC,0666);
	if(fd == -1){
		printf("->出了点小差错,请稍后重试 !\n");
		return;
	}
	char buf[100];
	ssize_t num = -1;
	memset(buf,0,100);
	num = read(lfd,buf,100);
	if(num < 0){
		printf("->read error ! \n");
		return;
	}
	if( strncmp(buf,"error",4) == 0 )
	{
		printf("->文件名错误,请重试 !\n");
		int re = unlink(buff);
		if(re == -1)
		{
			perror("rmdir");
			return;
		}
		return;
	}

//	printf("%d\n",(int)num);
//	printf("%s\n",buf);

	ssize_t z = write(fd,buf,num);
	if(z == num)
	{
		printf("->文件下载完毕\n");
		close(fd);
	}else{
		printf("->Download error !\n");
	}
}
void Upload(int lfd)
{
	node msg;
	msg.type = 'U';
	strcpy(msg.username,name);
	memset(buff,0,SIZE);
	printf("->输入要上传的文件名:\n->");
	fgets(buff,SIZE,stdin);
	if(buff[strlen(buff)-1] == '\n')
		buff[strlen(buff)-1] = '\0';
	strcpy(msg.passwold,buff);
	write(lfd,&msg,sizeof(msg));
	int fd = open(buff,O_RDONLY);
	if(fd == -1){
		printf("->上传文件失败,检查一下文件名呢?\n");
		return;
	}
	char buf[100];
	int num = read(fd,buf,100);
	if( num < 0 ){
		printf("->read error ! \n");
		close(fd);
		return;
	}
	else if( num == 0 ){
		printf("->文件上传完毕\n");
		close(fd);
		return;
	}else{
		write(lfd,buf,num);
		printf("->文件上传完毕\n");
	}
	close(fd);
	return;
}

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值