使用技术
- 采用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;
}