注册两个账号,用户名和密码分别为hujing、hello和zjy、123;
登陆hujing账号,上传一个路径为/home/hujing/Desktop/homework/long的文件,可以看到网盘的文件夹中下载到了一个命名为hujing_file的文件,且该文件头四个字节为该文件的密码;
当用户下载自己上传的文件时,不需要输入密码;这里为用户hujing下载自己上传的文件file,下载的文件命名为xixi
当用户下载别的用户上传的文件时,需要输入密码;这里为用户zjy登陆下载用户hujing上传的文件file,下载的文件命名为haha,此时需要输入密码3728,可以看到下载成功;
网盘server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>unsigned short port = 8990; // 本地端口
int sockfd=0;
int connfd=0;
//char id[50];void setserver()
{//创建套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);if(sockfd < 0){perror("socket");exit(-1);}//设置本地地址结构体struct sockaddr_in my_addr;bzero(&my_addr, sizeof(my_addr)); // 清空,保证最后8字节为0my_addr.sin_family = AF_INET; // ipv4my_addr.sin_port = htons(port); // 端口my_addr.sin_addr.s_addr = htonl(INADDR_ANY);// ip,INADDR_ANY为通配地址其值为0//将本地ip、端口与套接字socket相关联起来int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));if( err_log == -1){perror("binding");close(sockfd);exit(-1);}//监听,监听套接字改为被动,创建连接队列err_log = listen(sockfd, 10);if(err_log == -1){perror("listen");close(sockfd);exit(-1);}printf("server at port=%d...\n",port);
}void hjregister()
{char send_buf[1024];char recv_buf[1024];char id[50];char password[100];//printf("connfd=%d\n",*connfd);//读取注册信息并存入文件recv(connfd,id,sizeof(id),0);recv(connfd,password,sizeof(password),0);int fd=open("/home/hujing/hj/fileuseridinf",O_WRONLY|O_APPEND);//将name和写入文件sprintf(send_buf,"%s\t%s\n",id,password);write(fd,send_buf,strlen(send_buf));printf("已存入文件 %s %s\n",id,password);bzero(send_buf,strlen(send_buf));close(fd);
}void upload(char id[50])
{//recv用户发过来的文件路径 打开该文件并 读取char filepath[100];recv(connfd,filepath,sizeof(filepath),0);//recv网盘中文件名char filename[50];recv(connfd,filename,sizeof(filename),0);//密码char password[20];recv(connfd,password,sizeof(password),0);//在服务器所在文件夹创建一个新的文件 命名为char newpath[150];sprintf(newpath,"/home/hujing/hj/file/%s_%s",id,filename); //open用户路径和网盘中文件路径int ofd=open(filepath,O_RDONLY);if(ofd<0) {send(connfd,"PATH ERROR",strlen("PATH ERROR"),0);printf("PATH ERROR\n");close(ofd);return;}int ifd=open(newpath,O_CREAT|O_WRONLY,0777);//一次read1024个字节并记录int readsize=1024;int writesize=0;int cnt=0;writesize=write(ifd,password,4);while(readsize==1024){char temp[1024];readsize=read(ofd,temp,sizeof(temp));//printf("%d readsize=%d\n",cnt+1,readsize);writesize=write(ifd,temp,readsize);cnt++;} char send_buf[1024];bzero(send_buf,sizeof(send_buf));sprintf(send_buf,"SUCCESS 共读取到%d个字节",1024*(cnt-1)+readsize);send(connfd,send_buf,strlen(send_buf),0);close(ifd);close(ofd);
}void download(char id[50])
{//printf("download\n");int flag=1;char owner[50];recv(connfd,owner,sizeof(owner),0);char filename[50];recv(connfd,filename,sizeof(filename),0);char newpath[100];recv(connfd,newpath,sizeof(newpath),0);char password[50];if(strcmp(owner,id)!=0){recv(connfd,password,sizeof(password),0);flag=0;}char filepath[150];bzero(filepath,sizeof(filepath));sprintf(filepath,"/home/hujing/hj/file/%s_%s",owner,filename);int ofd=open(filepath,O_RDONLY);//recv stor filepathint readsize=1024;int writesize=0;int cnt=0;if(ofd<0) {send(connfd,"nameerror",strlen("nameerror"),0);//printf("NAME ERROR\n");perror("file open");close(ofd);return;}else{int ifd=open(newpath,O_CREAT|O_WRONLY,0777);send(connfd,"namecorrect",strlen("namecorrect"),0);char truepass[20];read(ofd,truepass,4);if(strcmp(owner,id)!=0){if(strcmp(password,truepass)==0)flag=1;else send(connfd,"passworderror",strlen("passworderror"),0);}if(flag)while(readsize==1024){char temp[1024];readsize=read(ofd,temp,sizeof(temp));//printf("%d readsize=%d\n",cnt+1,readsize);writesize=write(ifd,temp,readsize);cnt++;}close(ifd);}char send_buf[1024];bzero(send_buf,sizeof(send_buf));sprintf(send_buf,"SUCCESS 共下载到%d个字节",1024*(cnt-1)+readsize);printf("%s共下载%d个字节\n",id,1024*(cnt-1)+readsize);send(connfd,send_buf,strlen(send_buf),0);close(ofd);
}void checkdir()
{printf("checkdir\n");char send_buf[1024];char temp[1024];bzero(temp,sizeof(temp));bzero(send_buf,sizeof(send_buf));DIR *dir;struct dirent *entry;dir=opendir("/home/hujing/hj/file");while((entry=readdir(dir))!=NULL){if(strcmp(entry->d_name,".")==0 || strcmp(entry->d_name,"..")==0)continue;else {//printf("%s\t",entry->d_name);strcpy(temp,send_buf);sprintf(send_buf,"%s %s",entry->d_name,temp);}}send(connfd,send_buf,strlen(send_buf),0);closedir(dir);
}void hjlogin()
{char recv_buf[1024];char send_buf[1024];char id[50];char searchid[50];bzero(searchid,sizeof(searchid));recv(connfd,searchid,sizeof(searchid),0);char searchpass[100];bzero(searchpass,sizeof(searchpass));recv(connfd,searchpass,sizeof(searchpass),0);int fd=open("/home/hujing/hj/fileuseridinf",O_RDONLY);bzero(send_buf,sizeof(send_buf));read(fd,send_buf,sizeof(send_buf));close(fd);int i=0;int j=0;char temp[150];//存储一条信息int flag=0;//判断密码是否输入正确char success[20]="LOGINSUCCESS";for(int i=0;i<(int)strlen(send_buf);i++){if(send_buf[i]-'\n'!=0) temp[j]=send_buf[i];else{char tempid[50];char temppass[100];sscanf(temp,"%s\t%s",tempid,temppass);if(strcmp(tempid,searchid)==0&&strcmp(searchpass,temppass)==0){send(connfd,success,strlen(success),0);printf("\t%s LOG IN\n",tempid);flag=1;strcpy(id,tempid);break;}j=-1;bzero(temp,strlen(temp));}j++;}if(flag){int flag1=0;while(1){//recvbzero(recv_buf,strlen(recv_buf));recv(connfd,recv_buf,sizeof(recv_buf),0);//菜单 上传/下载/查看目录char select=recv_buf[1];switch(select){case '1':upload(id);break;//上传case '2':download(id);break;//下载case '3':checkdir();break;//查看目录case '4':flag1=1;break;//退出}if(flag1) break;}}else send(connfd,"failure",strlen("failure"),0);
}void run()
{pthread_detach(pthread_self());char recv_buf[1024];int flag=0;while(1){bzero(recv_buf,strlen(recv_buf));recv(connfd,recv_buf,sizeof(recv_buf),0);char select=recv_buf[1];switch(select){case '1':hjregister();break;//注册case '2':hjlogin();break;//登陆case '3':flag=1;break;//退出}if(flag) break;}
}int main()
{setserver();struct sockaddr_in client_addr;char cli_ip[INET_ADDRSTRLEN] = ""; //INET...是ipv4的长度socklen_t cliaddr_len = sizeof(client_addr); //socklen_t 一种数据类型 accept函数中第三个参数的长度必须和int相同 32和64位 下的socklen_t和int长度不同while(1){umask(0000);int fd=open("/home/hujing/hj/fileuseridinf",O_CREAT,0777);//存储idconnfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);if(connfd<0){perror("accept");continue;}inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);printf("\nclient ip=%s,port=%d,connfd=%d\n", cli_ip,ntohs(client_addr.sin_port),connfd);pthread_t pth;pthread_create(&pth,NULL,run,&connfd);}return 0;
}
网盘client.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>unsigned short port = 8990; // 服务器的端口号
char *server_ip = "127.0.0.1"; // 服务器ip地址
int sockfd;
char id[50];
char send_buf[512];
char recv_buf[512];void setclient()
{sockfd = socket(AF_INET, SOCK_STREAM, 0);// 创建套接字if(sockfd < 0){perror("socket");exit(-1);}// 设置服务器地址结构体struct sockaddr_in server_addr;bzero(&server_addr,sizeof(server_addr)); // 初始化服务器地址server_addr.sin_family = AF_INET; // IPv4server_addr.sin_port = htons(port); // 端口inet_pton(AF_INET, server_ip, &server_addr.sin_addr.s_addr); // 转换ip地址格式// 主动连接服务器int err_log = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));if(err_log != 0){perror("connect");exit(-1);}
}void hjregister()
{//注册printf(">>>input your name:");scanf("%s",id);send(sockfd,id,strlen(id),0);printf("\n>>>input your password:");scanf("%s",send_buf);send(sockfd,send_buf,strlen(send_buf),0);bzero(send_buf,sizeof(send_buf));
}void upload()
{//printf("upload\n");//send服务器filepath & filenameprintf(">>>input upload filepath:");char filepath[100];scanf("%s",filepath);send(sockfd,filepath,strlen(filepath),0);printf(">>>input upload filename:");char filename[100];scanf("%s",filename);send(sockfd,filename,strlen(filename),0);printf(">>>input password:");char password[20];scanf("%s",password);send(sockfd,password,strlen(password),0);//接收服务器发的success or failurebzero(recv_buf,sizeof(recv_buf));recv(sockfd,recv_buf,sizeof(recv_buf),0);printf("%s\n",recv_buf);
}void download()
{//发名字//printf("download\n");printf(">>>input download file owner:");char owner[50];scanf("%s",owner);send(sockfd,owner,strlen(owner),0);printf(">>>input download file name:");char filename[100];scanf("%s",filename);send(sockfd,filename,strlen(filename),0);printf(">>>input upload file path:");char filepath[100];scanf("%s",filepath);send(sockfd,filepath,strlen(filepath),0);if(strcmp(owner,id)!=0){printf(">>>input download file password(4):");char password[50];scanf("%s",password);send(sockfd,password,strlen(password),0);}//收反馈消息bzero(recv_buf,sizeof(recv_buf));recv(sockfd,recv_buf,sizeof(recv_buf),0);if(strcmp("nameerror",recv_buf)==0) printf("NAME ERROR\n");else//接收反馈消息{bzero(recv_buf,sizeof(recv_buf));recv(sockfd,recv_buf,sizeof(recv_buf),0);if(strcmp(recv_buf,"passworderror")==0) printf("PASSWORD ERROR\n");else printf("%s\n",recv_buf);}
}void checkdir()
{bzero(recv_buf,sizeof(recv_buf));recv(sockfd,recv_buf,sizeof(recv_buf),0);printf("网盘中文件如下:\n%s\n",recv_buf);
}void hjlogin()
{//登陆printf(">>>input your name:");scanf("%s",send_buf);bzero(id,sizeof(id));strcpy(id,send_buf);send(sockfd,send_buf,strlen(send_buf),0);bzero(send_buf,sizeof(send_buf));printf("\n>>>input your password:");scanf("%s",send_buf);send(sockfd,send_buf,strlen(send_buf),0);bzero(send_buf,sizeof(send_buf));//验证bzero(recv_buf,sizeof(recv_buf));recv(sockfd,recv_buf,sizeof(recv_buf),0);char success[20]="LOGINSUCCESS";if(strcmp(recv_buf,success)==0){int flag=0;printf("\n\nLOG IN SUCCESS\n\n");while(1){//功能菜单 上传/下载/查看目录printf("\t功能\n");printf("\t1.upload\n");printf("\t2.download\n");printf("\t3.check directory\n");printf("\t4.back\n");int select=0;scanf("%d",&select);bzero(send_buf,sizeof(send_buf));send_buf[0]='*';switch(select){case 1:send_buf[1]='1';break;case 2:send_buf[1]='2';break;case 3:send_buf[1]='3';break;case 4:send_buf[1]='4';break;}send_buf[2]='*';send(sockfd,send_buf,strlen(send_buf),0);bzero(send_buf,sizeof(send_buf));switch(select){case 1:upload();break;//上传case 2:download();break;//下载case 3:checkdir();break;//查看目录case 4:flag=1;break;//退出}if(flag) break;}}else printf("用户名或密码不正确\n");
}void menu()
{int flag=0;while(1){printf("\t菜单\n");printf("\t1.register\n");printf("\t2.log in\n");printf("\t3.exit\n");int select=0;scanf("%d",&select);bzero(send_buf,sizeof(send_buf));send_buf[0]='*';switch(select){case 1:send_buf[1]='1';break;case 2:send_buf[1]='2';break;case 3:send_buf[1]='3';break;}send_buf[2]='*';send(sockfd,send_buf,strlen(send_buf),0);bzero(send_buf,sizeof(send_buf));switch(select){case 1:hjregister();break;//注册case 2:hjlogin();break;//登陆case 3:flag=1;break;//退出}if(flag) break;}
}int main(int argc, char *argv[])
{setclient();menu();close(sockfd);return 0;
}