各位好呀!这一小节应该就是这个小小网盘程序的最后一小节了,这一节将实现最后的三个功能,即列出用户在服务器中的文件列表,还有删除用户在服务器中的文件,最后的可以共享文件给好友。

  列出用户在服务器中的文件列表

  增加一个结构体

 struct FileList
{
int cnt;
char list[][];
};

  为了方便我就假设服务器最多可以存16个单个用户的文件。如果想要支持更多的文件,这里可以增加一个int pages;用于分页作用,我们在服务器中获取文件时,可以根据分页进行发送。这样既方便又能支持多文件。

  client.cpp这个客户端文件增加一个函数

 int file_list(struct Addr addr,struct User user)
{
struct sockaddr_in servAddr;
struct hostent *host;
struct Control control;
struct FileList filelist;
int sockfd; host=gethostbyname(addr.host);
servAddr.sin_family=AF_INET;
servAddr.sin_addr=*((struct in_addr *)host->h_addr);
servAddr.sin_port=htons(addr.port);
if(host==NULL)
{
perror("获取IP地址失败");
exit(-);
}
if((sockfd=socket(AF_INET,SOCK_STREAM,))==-)
{
perror("socket创建失败");
exit(-);
}
if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-)
{
perror("connect 失败");
exit(-);
} //控制信号
control.control=FILE_LIST;
control.uid=user.uid;
if(send(sockfd,(char *)&control,sizeof(struct Control),)<)
{
perror("文件指纹发送失败");
exit(-);
}
if(recv(sockfd,(char *)&filelist,sizeof(struct FileList),)<)
{
perror("获取文件列表失败");
exit(-);
}
for(int i=;i<filelist.cnt;i++)
{
printf("--> %s\n",filelist.list[i]);
} close(sockfd);
return ;
}

  然后在主函数中调用即可。

  server.cpp实现,在主函数的case FILE_LIST:处修改如下

  case FILE_LIST:
{
struct File file;
struct FileList filelist;
file.uid=control.uid;
mysql_get_file_list(file,&filelist);
send(clientfd,(char *)&filelist,sizeof(struct FileList),);
break;
}

  然后再增加一个对应的mysql_get_file_list函数

 int mysql_get_file_list(struct File file,struct FileList *filelist)
{
MYSQL conn;
MYSQL_RES * res_ptr;
MYSQL_ROW result_row;
int res;int row;int column;
int i,j;
char sql[]={};
char ch[];
//select filename from files,relations where relations.uid=[file].uid and relations.fid=files.fid;
strcpy(sql,"select filename from files,relations where relations.uid=");
sprintf(ch,"%d",file.uid);
strcat(sql,ch);
strcat(sql," and relations.fid=files.fid ;");
//printf("==>%s\n",sql); mysql_init(&conn);
if(mysql_real_connect(&conn,"localhost","root","","filetranslate",,NULL,CLIENT_FOUND_ROWS))
{
res=mysql_query(&conn,sql);
if(res)
{
perror("select sql error1");
}
else
{
res_ptr=mysql_store_result(&conn);
if(res_ptr)
{
column=mysql_num_fields(res_ptr);
row=mysql_num_rows(res_ptr)+;
//按行输出结果
filelist->cnt=row-;
for(i=;i<row;i++)
{
result_row=mysql_fetch_row(res_ptr);
strcpy(filelist->list[i-],result_row[]);
//printf("%s",result_row[0]);
}
}
else
{
printf("没有数据\n");
}
}
}
else
{
perror("Connect Failed1\n");
exit(-);
}
mysql_close(&conn);
return ;
}

  运行时的截图

  删除服务器中的用户文件

  在client.cpp中增加一个file_delete函数

 int file_delect(struct Addr addr,struct User user,char *filenames)
{
struct sockaddr_in servAddr;
struct hostent *host;
struct Control control;
struct File file;
int sockfd; host=gethostbyname(addr.host);
servAddr.sin_family=AF_INET;
servAddr.sin_addr=*((struct in_addr *)host->h_addr);
servAddr.sin_port=htons(addr.port);
if(host==NULL)
{
perror("获取IP地址失败");
exit(-);
}
if((sockfd=socket(AF_INET,SOCK_STREAM,))==-)
{
perror("socket创建失败");
exit(-);
}
if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-)
{
perror("connect 失败");
exit(-);
} //控制信号
control.control=FILE_DELECT;
control.uid=user.uid;
if(send(sockfd,(char *)&control,sizeof(struct Control),)<)
{
perror("文件指纹发送失败");
exit(-);
}
file.uid=user.uid;
strcpy(file.filename,filenames);
if(send(sockfd,(char *)&file,sizeof(struct File),)<)
{
perror("删除文件失败");
exit(-);
}
char ch[];
memset(ch,,sizeof(ch));
if(recv(sockfd,ch,sizeof(ch),)<)
{
perror("删除文件失败");
exit(-);
}
if(ch[]=='y') //删除成功
{
printf("删除成功\n");;
}
else if(ch[]=='n') //删除失败
{
printf("删除失败,确认是否有该文件\n");;
}
close(sockfd);
return ;
}

  在server.cpp的main函数中增加

 case FILE_DELECT:
{
struct File file;
char ch[];
memset(ch,,sizeof(ch));
recv(clientfd,(char *)&file,sizeof(struct File),);
int t=mysql_delete_file(file);
if(t==-)
{
printf("没有对应的文件\n");;
strcpy(ch,"no");
send(clientfd,ch,,);
break;
}
strcpy(ch,"yes");
send(clientfd,ch,,);
printf("删除成功\n");
break;
}

  然后在server.cpp中再增加一个mysql_delete_file函数

 int mysql_delete_file(struct File file)
{
MYSQL conn;
MYSQL_RES * res_ptr;
MYSQL_ROW result_row;
int res;int row;int column;
int i,j;
char sql[];
char ch[];
int fid;int rt=; mysql_init(&conn);
if(mysql_real_connect(&conn,"localhost","root","","filetranslate",,NULL,CLIENT_FOUND_ROWS))
{
//select files.fid from files,relations where relations.fid=files.fid and filename= [file].filename
strcpy(sql,"select files.fid from files,relations where relations.fid=files.fid and filename=\"");
strcat(sql,file.filename);
strcat(sql,"\";");
res=mysql_query(&conn,sql);
fid=;
if(res)
{
perror("Select Sql Error!");
}
else
{
res_ptr=mysql_store_result(&conn);
if(res_ptr)
{
column=mysql_num_fields(res_ptr);
row=mysql_num_rows(res_ptr)+;
if(row<=)
;
else
{
result_row=mysql_fetch_row(res_ptr);
if(result_row[]==NULL)
{
fid=;
}
else
{
fid=atoi(result_row[]);
}
}
}
else
{
fid=;
}
}
if(fid==)
{
mysql_close(&conn);
return -;
}
//根据获取到的fid然后删除relations对应fid和uid
//delect relations where uid='uid' and fid='fid'
strcpy(sql,"delete from relations where uid=");
sprintf(ch,"%d",file.uid);
strcat(sql,ch);
strcat(sql," and fid=");
sprintf(ch,"%d",fid);
strcat(sql,ch);
res=mysql_query(&conn,sql);
if(res)
{
printf("Delete Error\n");
}
else
{
;;
}
}
else
{
perror("Connect Failed!");
exit(-);
} mysql_close(&conn);
return rt;
}

  从上面的sql语句可以知道我们只是删除了relations表中的链接而已。而没有真正的删除已经上传上去的文件。这一点可以参考以前给过的资料。

  运行的截图如下

  文件共享给好友

  client.cpp文件加入一个函数

 int file_sendto(struct Addr addr,struct User user,char *filenames,struct User to)
{
struct sockaddr_in servAddr;
struct hostent *host;
struct Control control;
struct File file;
int sockfd; host=gethostbyname(addr.host);
servAddr.sin_family=AF_INET;
servAddr.sin_addr=*((struct in_addr *)host->h_addr);
servAddr.sin_port=htons(addr.port);
if(host==NULL)
{
perror("获取IP地址失败");
exit(-);
}
if((sockfd=socket(AF_INET,SOCK_STREAM,))==-)
{
perror("socket创建失败");
exit(-);
}
if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-)
{
perror("connect 失败");
exit(-);
} //控制信号
control.control=FILE_SENDTO;
control.uid=user.uid;
if(send(sockfd,(char *)&control,sizeof(struct Control),)<)
{
perror("文件指纹发送失败");
exit(-);
}
file.uid=user.uid;
strcpy(file.filename,filenames);
if(send(sockfd,(char *)&file,sizeof(struct File),)<)
{
perror("共享文件失败");
exit(-);
}
if(send(sockfd,(char *)&to,sizeof(struct User),)<)
{
perror("共享用户发送失败");
exit(-);
}
char ch[];
memset(ch,,sizeof(ch));
if(recv(sockfd,ch,sizeof(ch),)<)
{
perror("共享文件失败");
exit(-);
}
if(ch[]=='y') //删除成功
{
printf("共享成功\n");;
}
else if(ch[]=='n') //删除失败
{
if(ch[]=='')
printf("共享失败,确认是否有该文件\n");
else if(ch[]=='')
printf("共享失败,确认是否有该用户\n");
}
close(sockfd);
return ;
}

  而server.cpp在主函数main中switch中增加如下

 case FILE_SENDTO:
{
struct File file;
struct User to;
recv(clientfd,(char *)&file,sizeof(struct File),);
recv(clientfd,(char *)&to,sizeof(struct User),);
int t=mysql_sendto(file,to);
char ch[];
memset(ch,,sizeof(ch));
if(t==-)
{
printf("没有对应的文件\n");;
strcpy(ch,"no1");
send(clientfd,ch,,);
break;
}
else if(t==-)
{
printf("没有对应的用户\n");;
strcpy(ch,"no2");
send(clientfd,ch,,);
break;
}
strcpy(ch,"yes");
send(clientfd,ch,,);
printf("共享成功\n");
break;
}

  然后对应的增加下面一个函数

 int mysql_sendto(struct File file,struct User to)
{
//insert into relations values(uid,fid);
MYSQL conn;
MYSQL_RES * res_ptr;
MYSQL_ROW result_row;
int res;int row;int column;
int i,j;int fid;int uid;int rt=;
char sql[];
char ch[]; mysql_init(&conn);
if(mysql_real_connect(&conn,"localhost","root","","filetranslate",,NULL,CLIENT_FOUND_ROWS))
{
//select files.fid from files,relations where relations.fid=files.fid and filename=files.filename;
//得到fid后
strcpy(sql,"select files.fid from files,relations where relations.fid=files.fid and filename=\"");
strcat(sql,file.filename);
strcat(sql,"\";");
res=mysql_query(&conn,sql);
fid=;
if(res)
{
perror("Select Sql Error!");
}
else
{
res_ptr=mysql_store_result(&conn);
if(res_ptr)
{
column=mysql_num_fields(res_ptr);
row=mysql_num_rows(res_ptr)+;
if(row<=)
;
else
{
result_row=mysql_fetch_row(res_ptr);
if(result_row[]==NULL)
{
fid=;
}
else
{
fid=atoi(result_row[]);
}
}
}
else
{
fid=;
}
}
if(fid==)
{
mysql_close(&conn);
return -;//表示没有该文件
} //select uid from users where username=[to].username;
//得到uid后
strcpy(sql,"select uid from users where username=\"");
strcat(sql,to.username);
strcat(sql,"\"");
res=mysql_query(&conn,sql);
uid=;
if(res)
{
perror("Select Sql Error!");
}
else
{
res_ptr=mysql_store_result(&conn);
if(res_ptr)
{
column=mysql_num_fields(res_ptr);
row=mysql_num_rows(res_ptr)+;
if(row<=)
;
else
{
result_row=mysql_fetch_row(res_ptr);
if(result_row[]==NULL)
{
uid=;
}
else
{
uid=atoi(result_row[]);
}
}
}
else
{
uid=;
}
}
if(uid==)
{
mysql_close(&conn);
return -;//表示没有该用户
} //将获取到的uid fid插入到数据库relations中
//insert into relations values(uid,fid);
strcpy(sql,"insert into relations values( ");
sprintf(ch,"%d",uid);
strcat(sql,ch);
strcat(sql,", ");
sprintf(ch,"%d",fid);
strcat(sql,ch);
strcat(sql,");");
res=mysql_query(&conn,sql);
printf("==========> uid=%d fid=%d\n",uid,fid);
if(res)
{
rt=-;
printf("Insert Error\n");
}
else
{
printf("Insert Success\n");
}
}
else
{
perror("Connect Failed!");
exit(-);
}
mysql_close(&conn);
return rt;
}

  下面这个是运行时的截图

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

  从程序中可以看出很多代码是有冗余的,如果进行重构的话,估计代码可以节省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

Socket网络编程--小小网盘程序(5)的更多相关文章

  1. Socket网络编程--小小网盘程序(4)

    在这一小节中实现了文件的下载,具体的思路是根据用户的uid和用户提供的文件名filename联合两张表,取得md5唯一标识符,然后操作这个标识符对应的文件发送给客户端. 实现下载的小小网盘程序 cli ...

  2. Socket网络编程--小小网盘程序(2)

    这一节将不会介绍太多的技术的问题,这节主要是搭建一个小小的框架,为了方便接下来的继续编写扩展程序.本次会在上一小节的基础上加上一个身份验证的功能. 因为网盘程序不像聊天程序,网盘是属于主动向服务器拉取 ...

  3. Socket网络编程--小小网盘程序(3)

    接上一小节,这次增加另外的两张表,用于记录用户是保存那些文件.增加传上来的文件的文件指纹,使用MD5表示. 两张表如下定义: create table files( fid int, filename ...

  4. Socket网络编程--小小网盘程序(1)

    这个系列是准备讲基于Linux Socket进行文件传输.简单的文件传输就是客户端可以上传文件,可以从服务器端下载文件.就这么两个功能如果再加上身份验证,就成了FTP服务器了,如果对用户的操作再加上一 ...

  5. linux下C语言socket网络编程简例

    原创文章,转载请注明转载字样和出处,谢谢! 这里给出在linux下的简单socket网络编程的实例,使用tcp协议进行通信,服务端进行监听,在收到client的连接后,发送数据给client:clie ...

  6. 5.3linux下C语言socket网络编程简例

    原创文章,转载请注明转载字样和出处,谢谢! 这里给出在Linux下的简单socket网络编程的实例,使用tcp协议进行通信,服务端进行监听,在收到客户端的连接后,发送数据给客户端:客户端在接受到数据后 ...

  7. Socket网络编程--聊天程序(9)

    这一节应该是聊天程序的最后一节了,现在回顾我们的聊天程序,看起来还有很多功能没有实现,但是不管怎么说,都还是不错的.这一节我们将讲多服务器问题(高大上的说法就是负载问题了.)至于聊天程序的文件发送(也 ...

  8. Socket网络编程系列教程序

    C语言的用途相当多,可以用在数据结构.数据库.网络.嵌入式等方面,历经40多年不衰,真是厉害!最近一直想从某一应用方面写一个系列教程,好好地把某一方面讲深讲透.         正好博主对网络方面的编 ...

  9. Socket网络编程--FTP客户端

    Socket网络编程--FTP客户端(1)(Windows) 已经好久没有写过博客进行分享了.具体原因,在以后说. 这几天在了解FTP协议,准备任务是写一个FTP客户端程序.直接上干货了. 0.了解F ...

随机推荐

  1. 6-3 二叉树的重建 uva536

    已知先序和中序  求后序 可以有两种方式输出 一种是建好树按照树输出 一种是不建树  在遍历的过程中存入vector  再倒叙输出 #include<bits/stdc++.h> usin ...

  2. 6-17 看图写树 uva10562

    非常好的dfs题  有很多细节 关于‘ ’  ‘0’  ’\n‘  的处理  他们都属于isspace函数 其中 while(buf[x+2][i]=='-'&&buf[x+3][i] ...

  3. 【Java】 剑指offer(51)数组中的逆序对

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成 ...

  4. Topic路由模式

    原本理解的不够彻底,程序总是不太对.所以查询了资料,关于这种模式的意思做了仔细的解读,复制的文字. 一:介绍 1.模式 2.知识点 其中,#可以匹配一个或者多个字符 其中,*可以匹配一个字符 3.仔细 ...

  5. PHP 扩展 MongoDB

    打开phpinfo 查看 nts(非线程) 还是 ts (线程),操作位数: 下载对应的版本的php_mongodb.dll 文件 下载链接: pecl mangodb下载 把文件解压出来 php_m ...

  6. web漏洞扫描工具AWVS使用

    AWVS AWVS简介:Acunetix Web Vulnerability Scanner(简称AWVS)是一款知名的网络漏洞扫描工具,它通过网络爬虫测试你的网站安全,检测流行安全漏洞,如交叉站点脚 ...

  7. Windows环境下 PHP调用R脚本

    写在前面的: 由于是windows平台实现的,只要保证脚本命令能在cmd控制台运行,则可以在php中利用system()实现. 注意事项: (1).保证system的路径中无汉字和空格 !!  (亲身 ...

  8. Lakeshore 中文开发界面,示例项目,飞机大战 等 Lakeshore Chinese development interface, sample project, aircraft war, etc

    Lakeshore 中文开发界面,示例项目,飞机大战 等 Lakeshore Chinese development interface, sample project, aircraft war, ...

  9. Putty的用法

    大致内容罗列如下: ·        最简单的使用,登录 SSH主机 ·        中文乱码的处理 ·        PuTTY常用配置的说明 ·        复制.粘贴 ·        保存 ...

  10. 20172302 《Java软件结构与数据结构》实验一:线性结构实验报告

    课程:<Java软件结构与数据结构> 班级: 1723 姓名: 侯泽洋 学号:20172302 实验教师:王志强老师 实验日期:2018年9月26日 必修/选修: 必修 实验内容 (1)链 ...