各位好呀!这一小节应该就是这个小小网盘程序的最后一小节了,这一节将实现最后的三个功能,即列出用户在服务器中的文件列表,还有删除用户在服务器中的文件,最后的可以共享文件给好友。
列出用户在服务器中的文件列表
增加一个结构体
1 struct FileList
2 {
3 int cnt;
4 char list[16][128];
5 };
为了方便我就假设服务器最多可以存16个单个用户的文件。如果想要支持更多的文件,这里可以增加一个int pages;用于分页作用,我们在服务器中获取文件时,可以根据分页进行发送。这样既方便又能支持多文件。
client.cpp这个客户端文件增加一个函数
1 int file_list(struct Addr addr,struct User user)
2 {
3 struct sockaddr_in servAddr;
4 struct hostent *host;
5 struct Control control;
6 struct FileList filelist;
7 int sockfd;
8
9 host=gethostbyname(addr.host);
10 servAddr.sin_family=AF_INET;
11 servAddr.sin_addr=*((struct in_addr *)host->h_addr);
12 servAddr.sin_port=htons(addr.port);
13 if(host==NULL)
14 {
15 perror("获取IP地址失败");
16 exit(-1);
17 }
18 if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
19 {
20 perror("socket创建失败");
21 exit(-1);
22 }
23 if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-1)
24 {
25 perror("connect 失败");
26 exit(-1);
27 }
28
29 //控制信号
30 control.control=FILE_LIST;
31 control.uid=user.uid;
32 if(send(sockfd,(char *)&control,sizeof(struct Control),0)<0)
33 {
34 perror("文件指纹发送失败");
35 exit(-1);
36 }
37 if(recv(sockfd,(char *)&filelist,sizeof(struct FileList),0)<0)
38 {
39 perror("获取文件列表失败");
40 exit(-1);
41 }
42 for(int i=0;i<filelist.cnt;i++)
43 {
44 printf("--> %s\n",filelist.list[i]);
45 }
46
47 close(sockfd);
48 return 0;
49 }
然后在主函数中调用即可。
server.cpp实现,在主函数的case FILE_LIST:处修改如下
1 case FILE_LIST:
2 {
3 struct File file;
4 struct FileList filelist;
5 file.uid=control.uid;
6 mysql_get_file_list(file,&filelist);
7 send(clientfd,(char *)&filelist,sizeof(struct FileList),0);
8 break;
9 }
然后再增加一个对应的mysql_get_file_list函数
1 int mysql_get_file_list(struct File file,struct FileList *filelist)
2 {
3 MYSQL conn;
4 MYSQL_RES * res_ptr;
5 MYSQL_ROW result_row;
6 int res;int row;int column;
7 int i,j;
8 char sql[256]={0};
9 char ch[64];
10 //select filename from files,relations where relations.uid=[file].uid and relations.fid=files.fid;
11 strcpy(sql,"select filename from files,relations where relations.uid=");
12 sprintf(ch,"%d",file.uid);
13 strcat(sql,ch);
14 strcat(sql," and relations.fid=files.fid ;");
15 //printf("==>%s\n",sql);
16
17 mysql_init(&conn);
18 if(mysql_real_connect(&conn,"localhost","root","","filetranslate",0,NULL,CLIENT_FOUND_ROWS))
19 {
20 res=mysql_query(&conn,sql);
21 if(res)
22 {
23 perror("select sql error1");
24 }
25 else
26 {
27 res_ptr=mysql_store_result(&conn);
28 if(res_ptr)
29 {
30 column=mysql_num_fields(res_ptr);
31 row=mysql_num_rows(res_ptr)+1;
32 //按行输出结果
33 filelist->cnt=row-1;
34 for(i=1;i<row;i++)
35 {
36 result_row=mysql_fetch_row(res_ptr);
37 strcpy(filelist->list[i-1],result_row[0]);
38 //printf("%s",result_row[0]);
39 }
40 }
41 else
42 {
43 printf("没有数据\n");
44 }
45 }
46 }
47 else
48 {
49 perror("Connect Failed1\n");
50 exit(-1);
51 }
52 mysql_close(&conn);
53 return 0;
54 }
运行时的截图

删除服务器中的用户文件
在client.cpp中增加一个file_delete函数
1 int file_delect(struct Addr addr,struct User user,char *filenames)
2 {
3 struct sockaddr_in servAddr;
4 struct hostent *host;
5 struct Control control;
6 struct File file;
7 int sockfd;
8
9 host=gethostbyname(addr.host);
10 servAddr.sin_family=AF_INET;
11 servAddr.sin_addr=*((struct in_addr *)host->h_addr);
12 servAddr.sin_port=htons(addr.port);
13 if(host==NULL)
14 {
15 perror("获取IP地址失败");
16 exit(-1);
17 }
18 if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
19 {
20 perror("socket创建失败");
21 exit(-1);
22 }
23 if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-1)
24 {
25 perror("connect 失败");
26 exit(-1);
27 }
28
29 //控制信号
30 control.control=FILE_DELECT;
31 control.uid=user.uid;
32 if(send(sockfd,(char *)&control,sizeof(struct Control),0)<0)
33 {
34 perror("文件指纹发送失败");
35 exit(-1);
36 }
37 file.uid=user.uid;
38 strcpy(file.filename,filenames);
39 if(send(sockfd,(char *)&file,sizeof(struct File),0)<0)
40 {
41 perror("删除文件失败");
42 exit(-1);
43 }
44 char ch[32];
45 memset(ch,0,sizeof(ch));
46 if(recv(sockfd,ch,sizeof(ch),0)<0)
47 {
48 perror("删除文件失败");
49 exit(-1);
50 }
51 if(ch[0]=='y') //删除成功
52 {
53 printf("删除成功\n");;
54 }
55 else if(ch[0]=='n') //删除失败
56 {
57 printf("删除失败,确认是否有该文件\n");;
58 }
59 close(sockfd);
60 return 0;
61 }
在server.cpp的main函数中增加
1 case FILE_DELECT:
2 {
3 struct File file;
4 char ch[64];
5 memset(ch,0,sizeof(ch));
6 recv(clientfd,(char *)&file,sizeof(struct File),0);
7 int t=mysql_delete_file(file);
8 if(t==-1)
9 {
10 printf("没有对应的文件\n");;
11 strcpy(ch,"no");
12 send(clientfd,ch,64,0);
13 break;
14 }
15 strcpy(ch,"yes");
16 send(clientfd,ch,64,0);
17 printf("删除成功\n");
18 break;
19 }
然后在server.cpp中再增加一个mysql_delete_file函数
1 int mysql_delete_file(struct File file)
2 {
3 MYSQL conn;
4 MYSQL_RES * res_ptr;
5 MYSQL_ROW result_row;
6 int res;int row;int column;
7 int i,j;
8 char sql[256];
9 char ch[64];
10 int fid;int rt=0;
11
12 mysql_init(&conn);
13 if(mysql_real_connect(&conn,"localhost","root","","filetranslate",0,NULL,CLIENT_FOUND_ROWS))
14 {
15 //select files.fid from files,relations where relations.fid=files.fid and filename= [file].filename
16 strcpy(sql,"select files.fid from files,relations where relations.fid=files.fid and filename=\"");
17 strcat(sql,file.filename);
18 strcat(sql,"\";");
19 res=mysql_query(&conn,sql);
20 fid=0;
21 if(res)
22 {
23 perror("Select Sql Error!");
24 }
25 else
26 {
27 res_ptr=mysql_store_result(&conn);
28 if(res_ptr)
29 {
30 column=mysql_num_fields(res_ptr);
31 row=mysql_num_rows(res_ptr)+1;
32 if(row<=1)
33 ;
34 else
35 {
36 result_row=mysql_fetch_row(res_ptr);
37 if(result_row[0]==NULL)
38 {
39 fid=0;
40 }
41 else
42 {
43 fid=atoi(result_row[0]);
44 }
45 }
46 }
47 else
48 {
49 fid=0;
50 }
51 }
52 if(fid==0)
53 {
54 mysql_close(&conn);
55 return -1;
56 }
57 //根据获取到的fid然后删除relations对应fid和uid
58 //delect relations where uid='uid' and fid='fid'
59 strcpy(sql,"delete from relations where uid=");
60 sprintf(ch,"%d",file.uid);
61 strcat(sql,ch);
62 strcat(sql," and fid=");
63 sprintf(ch,"%d",fid);
64 strcat(sql,ch);
65 res=mysql_query(&conn,sql);
66 if(res)
67 {
68 printf("Delete Error\n");
69 }
70 else
71 {
72 ;;
73 }
74 }
75 else
76 {
77 perror("Connect Failed!");
78 exit(-1);
79 }
80
81 mysql_close(&conn);
82 return rt;
83 }
从上面的sql语句可以知道我们只是删除了relations表中的链接而已。而没有真正的删除已经上传上去的文件。这一点可以参考以前给过的资料。
运行的截图如下

文件共享给好友
client.cpp文件加入一个函数
1 int file_sendto(struct Addr addr,struct User user,char *filenames,struct User to)
2 {
3 struct sockaddr_in servAddr;
4 struct hostent *host;
5 struct Control control;
6 struct File file;
7 int sockfd;
8
9 host=gethostbyname(addr.host);
10 servAddr.sin_family=AF_INET;
11 servAddr.sin_addr=*((struct in_addr *)host->h_addr);
12 servAddr.sin_port=htons(addr.port);
13 if(host==NULL)
14 {
15 perror("获取IP地址失败");
16 exit(-1);
17 }
18 if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
19 {
20 perror("socket创建失败");
21 exit(-1);
22 }
23 if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-1)
24 {
25 perror("connect 失败");
26 exit(-1);
27 }
28
29 //控制信号
30 control.control=FILE_SENDTO;
31 control.uid=user.uid;
32 if(send(sockfd,(char *)&control,sizeof(struct Control),0)<0)
33 {
34 perror("文件指纹发送失败");
35 exit(-1);
36 }
37 file.uid=user.uid;
38 strcpy(file.filename,filenames);
39 if(send(sockfd,(char *)&file,sizeof(struct File),0)<0)
40 {
41 perror("共享文件失败");
42 exit(-1);
43 }
44 if(send(sockfd,(char *)&to,sizeof(struct User),0)<0)
45 {
46 perror("共享用户发送失败");
47 exit(-1);
48 }
49 char ch[32];
50 memset(ch,0,sizeof(ch));
51 if(recv(sockfd,ch,sizeof(ch),0)<0)
52 {
53 perror("共享文件失败");
54 exit(-1);
55 }
56 if(ch[0]=='y') //删除成功
57 {
58 printf("共享成功\n");;
59 }
60 else if(ch[0]=='n') //删除失败
61 {
62 if(ch[2]=='1')
63 printf("共享失败,确认是否有该文件\n");
64 else if(ch[2]=='2')
65 printf("共享失败,确认是否有该用户\n");
66 }
67 close(sockfd);
68 return 0;
69 }
而server.cpp在主函数main中switch中增加如下
1 case FILE_SENDTO:
2 {
3 struct File file;
4 struct User to;
5 recv(clientfd,(char *)&file,sizeof(struct File),0);
6 recv(clientfd,(char *)&to,sizeof(struct User),0);
7 int t=mysql_sendto(file,to);
8 char ch[64];
9 memset(ch,0,sizeof(ch));
10 if(t==-1)
11 {
12 printf("没有对应的文件\n");;
13 strcpy(ch,"no1");
14 send(clientfd,ch,64,0);
15 break;
16 }
17 else if(t==-2)
18 {
19 printf("没有对应的用户\n");;
20 strcpy(ch,"no2");
21 send(clientfd,ch,64,0);
22 break;
23 }
24 strcpy(ch,"yes");
25 send(clientfd,ch,64,0);
26 printf("共享成功\n");
27 break;
28 }
然后对应的增加下面一个函数
1 int mysql_sendto(struct File file,struct User to)
2 {
3 //insert into relations values(uid,fid);
4 MYSQL conn;
5 MYSQL_RES * res_ptr;
6 MYSQL_ROW result_row;
7 int res;int row;int column;
8 int i,j;int fid;int uid;int rt=0;
9 char sql[256];
10 char ch[64];
11
12 mysql_init(&conn);
13 if(mysql_real_connect(&conn,"localhost","root","","filetranslate",0,NULL,CLIENT_FOUND_ROWS))
14 {
15 //select files.fid from files,relations where relations.fid=files.fid and filename=files.filename;
16 //得到fid后
17 strcpy(sql,"select files.fid from files,relations where relations.fid=files.fid and filename=\"");
18 strcat(sql,file.filename);
19 strcat(sql,"\";");
20 res=mysql_query(&conn,sql);
21 fid=0;
22 if(res)
23 {
24 perror("Select Sql Error!");
25 }
26 else
27 {
28 res_ptr=mysql_store_result(&conn);
29 if(res_ptr)
30 {
31 column=mysql_num_fields(res_ptr);
32 row=mysql_num_rows(res_ptr)+1;
33 if(row<=1)
34 ;
35 else
36 {
37 result_row=mysql_fetch_row(res_ptr);
38 if(result_row[0]==NULL)
39 {
40 fid=0;
41 }
42 else
43 {
44 fid=atoi(result_row[0]);
45 }
46 }
47 }
48 else
49 {
50 fid=0;
51 }
52 }
53 if(fid==0)
54 {
55 mysql_close(&conn);
56 return -1;//表示没有该文件
57 }
58
59 //select uid from users where username=[to].username;
60 //得到uid后
61 strcpy(sql,"select uid from users where username=\"");
62 strcat(sql,to.username);
63 strcat(sql,"\"");
64 res=mysql_query(&conn,sql);
65 uid=0;
66 if(res)
67 {
68 perror("Select Sql Error!");
69 }
70 else
71 {
72 res_ptr=mysql_store_result(&conn);
73 if(res_ptr)
74 {
75 column=mysql_num_fields(res_ptr);
76 row=mysql_num_rows(res_ptr)+1;
77 if(row<=1)
78 ;
79 else
80 {
81 result_row=mysql_fetch_row(res_ptr);
82 if(result_row[0]==NULL)
83 {
84 uid=0;
85 }
86 else
87 {
88 uid=atoi(result_row[0]);
89 }
90 }
91 }
92 else
93 {
94 uid=0;
95 }
96 }
97 if(uid==0)
98 {
99 mysql_close(&conn);
100 return -2;//表示没有该用户
101 }
102
103 //将获取到的uid fid插入到数据库relations中
104 //insert into relations values(uid,fid);
105 strcpy(sql,"insert into relations values( ");
106 sprintf(ch,"%d",uid);
107 strcat(sql,ch);
108 strcat(sql,", ");
109 sprintf(ch,"%d",fid);
110 strcat(sql,ch);
111 strcat(sql,");");
112 res=mysql_query(&conn,sql);
113 printf("==========> uid=%d fid=%d\n",uid,fid);
114 if(res)
115 {
116 rt=-1;
117 printf("Insert Error\n");
118 }
119 else
120 {
121 printf("Insert Success\n");
122 }
123 }
124 else
125 {
126 perror("Connect Failed!");
127 exit(-1);
128 }
129 mysql_close(&conn);
130 return rt;
131 }
下面这个是运行时的截图

在本次程序的最后,送上程序代码结构,及本人的开发环境。

从程序中可以看出很多代码是有冗余的,如果进行重构的话,估计代码可以节省50%。可怕的新手啊(◑﹏◐)。从代码量上看,这次的代码量也不少了,相比与上次聊天程序,代码量有过之而不及,不过可喜的是这次都把具体的功能封装成一个一个的函数,即使有冗余代码。不过还是有点小进步了。
Socket网络编程--小小网盘程序各个小节的传送门
Socket网络编程--小小网盘程序(1) http://www.cnblogs.com/wunaozai/p/3886588.html
Socket网络编程--小小网盘程序(2) http://www.cnblogs.com/wunaozai/p/3887728.html
Socket网络编程--小小网盘程序(3) http://www.cnblogs.com/wunaozai/p/3891062.html
Socket网络编程--小小网盘程序(4) http://www.cnblogs.com/wunaozai/p/3892729.html
Socket网络编程--小小网盘程序(5) http://www.cnblogs.com/wunaozai/p/3893469.html
本文地址: http://www.cnblogs.com/wunaozai/p/3893469.html
代码下载: http://files.cnblogs.com/wunaozai/xiaoxiaowangpan.zip
来源:https://www.cnblogs.com/wunaozai/p/3893469.html