各位好呀!這一小節應該就是這個小小網盤程序的最後一小節了,這一節將實現最後的三個功能,即列出用戶在服務器中的文件列表,還有刪除用戶在服務器中的文件,最後的能夠共享文件給好友。html
列出用戶在服務器中的文件列表mysql
增長一個結構體sql
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函數socket
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 }
運行時的截圖函數
刪除服務器中的用戶文件fetch
在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