注册两个账号,用户名和密码分别为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字节为0
my_addr.sin_family = AF_INET; // ipv4
my_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 filepath
int 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)
{
//recv
bzero(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);//存储id
connfd = 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; // IPv4
server_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 & filename
printf(">>>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 failure
bzero(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;
}