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

来源:互联网 发布:c语言视频夏老师 编辑:程序博客网 时间:2024/04/29 00:03

http://www.cnblogs.com/wunaozai/p/3887728.html

 这一节将不会介绍太多的技术的问题,这节主要是搭建一个小小的框架,为了方便接下来的继续编写扩展程序。本次会在上一小节的基础上加上一个身份验证的功能。

  因为网盘程序不像聊天程序,网盘是属于主动向服务器拉取信息,而聊天程序有可能要被动获取信息,所以为了减轻服务器压力,每次要向服务器获取服务就建立一个短连接,而不像聊天程序一样的长连接,微信的公众平台,输入指令获取服务,就是这个样子了。具体看一下代码就知道了。

  还有为了方便处理,我增加了一个控制信号,这个控制信号在以前的聊天程序中讲到过,但是当时为了简单就没有实现,现在就简单实现一些,方便以后可以参考。

  还有就是这次的网盘程序我将尽量实现下面的这些功能:

  (1) file push filename           //用户上传文件到服务器上

  (2) file pull filename            //用户下载文件到本地上

  (3) file list              //列出用户在服务器中的所有文件

  (4) file sendto  filename username //共享文件给其他用户

  (5) file delete filename        //删除服务器中的文件

  (6) 用户登录,自动完成

  本次数据库名为filetranslate,目前有表user

1 create table user2 (3     uid int;4     username varchar(64);5     password varchar(64);  6 );

 

  修改后的client.cpp

复制代码
  1 #include <netinet/in.h> // sockaddr_in  2 #include <sys/types.h> //socket  3 #include <sys/socket.h> //socket  4 #include <netdb.h> //gethostbyname  5 #include <unistd.h> //close  6 #include <stdio.h>  7 #include <stdlib.h>  8 #include <string.h>  9 #include <time.h> 10 #include <arpa/inet.h> //inet_addr 11  12 #define SERVVER_PORT 12138 13 #define LISTEN_QUEUE 20 14 #define BUFFER_SIZE 1024 15  16 //传输控制信号宏定义 17 //struct Control中control的取值 18 #define USER_CHECK_LOGIN 1 19 #define FILE_PUSH 2 20 #define FILE_PULL 3 21 #define FILE_LIST 4 22 #define FILE_SENDTO 5 23 #define FILE_DELECT 6 24  25 struct Addr 26 { 27     char host[64]; 28     int port; 29 }; 30 struct User 31 { 32     int uid; 33     char username[64]; 34     char password[64]; 35 }; 36 struct Control 37 { 38     int uid; 39     int control; 40 }; 41  42 void print_time(char *ch);//打印时间 43 int file_push(struct Addr addr,struct User user,char *filenames); 44 int check_login(struct Addr addr,struct User * user); 45  46  47 int main(int argc,char *argv[]) 48 { 49     char orderbuf[BUFFER_SIZE]; 50     struct Addr addr; 51     char arg1[32],arg2[32],arg3[32],arg4[32]; 52     struct User user; 53  54     if(argc!=5) 55     { 56         perror("usage: ./client [serverhost] [serverport] [username] [password]"); 57         exit(-1); 58     } 59     strcpy(addr.host,argv[1]); 60     addr.port=atoi(argv[2]); 61     strcpy(user.username,argv[3]); 62     strcpy(user.password,argv[4]); 63     int uid=check_login(addr,&user); 64     if(uid<=0) 65     { 66         perror("用户验证失败"); 67         exit(-1); 68     } 69     printf("验证登陆成功\n"); 70     while(1) 71     { 72         printf("\n请输入操作指令:"); 73         fgets(orderbuf,BUFFER_SIZE,stdin); 74         memset(arg1,0,sizeof(arg1)); 75         memset(arg2,0,sizeof(arg2)); 76         memset(arg3,0,sizeof(arg3)); 77         memset(arg4,0,sizeof(arg4)); 78         sscanf(orderbuf,"%s%s%s%s",arg1,arg2,arg3,arg4); 79         if(strcmp(arg1,"file")==0) 80         { 81             if(strcmp(arg2,"push")==0) 82             { 83                 strcpy(orderbuf,arg3); 84                 file_push(addr,user,orderbuf); 85             } 86             else if(strcmp(arg2,"pull")==0) 87             { 88                 ; 89             } 90             else if(strcmp(arg2,"list")==0) 91             { 92                 ; 93             } 94             else if(strcmp(arg2,"sendto")==0) 95             { 96                 ; 97             } 98             else if(strcmp(arg2,"delect")==0) 99             {100                 ;101             }102             else103             {104                 printf("该命令不支持\n");105             }106         }107         else108         {109             printf("该命令不支持\n");110         }111     }112 113 114     return 0;115 }116 117 //验证成功时返回大于0的uid号码,错误返回-1118 int check_login(struct Addr addr,struct User * user)119 {120     struct sockaddr_in servAddr;121     struct hostent * host;122     struct Control control;123     int sockfd;124 125     host=gethostbyname(addr.host);126     servAddr.sin_family=AF_INET;127     servAddr.sin_addr=*((struct in_addr *)host->h_addr);128     //servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");129     servAddr.sin_port=htons(addr.port);130     if(host==NULL)131     {132         perror("获取IP地址失败");133         exit(-1);134     }135     if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)136     {137         perror("socket创建失败");138         exit(-1);139     }140     if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-1)141     {142         perror("connect 失败");143         exit(-1);144     }145 146     control.control=USER_CHECK_LOGIN;147     control.uid=0;148     if(send(sockfd,(char *)&control,sizeof(struct Control),0)<0)149     {150         perror("发送数据失败");151         exit(-1);152     }153 154     if(send(sockfd,(char *)user,sizeof(struct User),0)<0)155     {156         perror("发送数据失败");157         exit(-1);158     }159     bzero(user,sizeof(struct User));160     if(recv(sockfd,(char *)user,sizeof(struct User),0)<0)161     {162         perror("接收数据失败");163         exit(-1);164     }165     printf("获取后用户名:%s 密码:%s ID号:%d\n",user->username,user->password,user->uid);166 167     close(sockfd);//关闭socket连接168     return user->uid;169 }170 171 int file_push(struct Addr addr,struct User user,char *filenames)172 {173     struct sockaddr_in servAddr;174     struct hostent * host;175     struct Control control;176     int sockfd;177     FILE *fp;178 179     host=gethostbyname(addr.host);180     servAddr.sin_family=AF_INET;181     servAddr.sin_addr=*((struct in_addr *)host->h_addr);182     //servAddr.sin_addr.s_addr=inet_addr("127.0.0.1");183     servAddr.sin_port=htons(addr.port);184     if(host==NULL)185     {186         perror("获取IP地址失败");187         exit(-1);188     }189     if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)190     {191         perror("socket创建失败");192         exit(-1);193     }194 195     if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-1)196     {197         perror("connect 失败");198         exit(-1);199     }200 201     //打开文件202     if((fp=fopen(filenames,"rb"))==NULL)203     {204         perror("文件打开失败");205         exit(-1);206     }207     //这里传输控制信号208     control.control=FILE_PUSH;209     control.uid=user.uid;210     if(send(sockfd,(char *)&control,sizeof(struct Control),0)<0)211     {212         perror("控制信号发送失败");213         exit(-1);214     }215     char buffer[BUFFER_SIZE];216     bzero(buffer,BUFFER_SIZE);217     printf("正在传输文件");218     int len=0;219     //不断的读取文件直到文件结束220     while((len=fread(buffer,1,BUFFER_SIZE,fp))>0)221     {222         if(send(sockfd,buffer,len,0)<0)223         {224             perror("发送数据失败");225             exit(-1);226         }227         bzero(buffer,BUFFER_SIZE);228         printf(".");//1K打印一个点//如果要实现百分比,就要计算文件大小,然后再处理即可229     }230 231     printf("传输完毕\n");232     fclose(fp);//关闭文件流233     close(sockfd);//关闭socket连接234 235     return 0;236 }237 238 void print_time(char *ch)239 {240     time_t now;241     struct tm * stm;242     time(&now);243     stm=localtime(&now);244     sprintf(ch,"%02d:%02d:%02d\n",stm->tm_hour,stm->tm_min,stm->tm_sec);245     return ;246 }
复制代码

  下面这个是server.cpp

复制代码
  1 #include <netinet/in.h>  2 #include <sys/types.h>  3 #include <sys/socket.h>  4 #include <sys/select.h>  5 #include <netdb.h>  6 #include <stdlib.h>  7 #include <time.h>  8 #include <string.h>  9 #include <unistd.h> 10 #include <stdio.h> 11 #include <arpa/inet.h> //inet_ntoa 12 #include <mysql.h> 13  14 #define SERVER_PORT 12138 15 #define LISTEN_QUEUE 20 16 #define BACKLOG 200 17 #define BUFFER_SIZE 1024 18  19 //传输控制信号宏定义 20 //struct Control中control的取值 21 #define USER_CHECK_LOGIN 1 22 #define FILE_PUSH 2 23 #define FILE_PULL 3 24 #define FILE_LIST 4 25 #define FILE_SENDTO 5 26 #define FILE_DELECT 6 27  28 struct User 29 { 30     int uid; 31     char username[64]; 32     char password[64]; 33 }; 34  35 struct Control 36 { 37     int uid; 38     int control; 39 }; 40  41 void print_time(char *ch);//打印时间 42 int MAX(int a,int b); 43 int mysql_check_login(struct User user); 44  45  46 int main(int argc,char *argv[]) 47 { 48     struct sockaddr_in server_addr; 49     struct sockaddr_in client_addr; 50     struct User user; 51     struct Control control; 52     char ch[64]; 53     int clientfd; 54     pid_t pid; 55     socklen_t length; 56     bzero(&server_addr,sizeof(server_addr)); 57     server_addr.sin_family=AF_INET; 58     server_addr.sin_addr.s_addr=htons(INADDR_ANY); 59     server_addr.sin_port=htons(SERVER_PORT); 60  61     //创建套接字 62     int sockfd=socket(AF_INET,SOCK_STREAM,0); 63     if(sockfd<0) 64     { 65         perror("创建套接字失败"); 66         exit(-1); 67     } 68  69     if(bind(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr))==-1) 70     { 71         perror("bind 失败"); 72         exit(-1); 73     } 74  75     if(listen(sockfd,LISTEN_QUEUE)) 76     { 77         perror("listen 失败"); 78         exit(-1); 79     } 80  81     length=sizeof(struct sockaddr); 82  83     while(1) 84     { 85         clientfd=accept(sockfd,(struct sockaddr *)&client_addr,&length); 86         if(clientfd==-1) 87         { 88             perror("accept 失败"); 89             continue; 90         } 91         printf(">>>>>%s:%d 连接成功,当前所在的ID(fd)号: %d \n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),clientfd); 92         print_time(ch); 93         printf("加入的时间是:%s\n",ch); 94  95         //来一个连接就创建一个进程进行处理 96         pid=fork(); 97         if(pid<0) 98         { 99             perror("fork error");100         }101         else if(pid==0)102         {103             recv(clientfd,(char *)&control,sizeof(struct Control),0);104             printf("用户 %d 使用命令 %d\n",control.uid,control.control);105             switch(control.control)106             {107                 case USER_CHECK_LOGIN:108                     {109                         //身份验证处理110                         recv(clientfd,(char *)&user,sizeof(struct User),0);111                         printf("客户端发送过来的用户名是:%s,密码:%s\n",user.username,user.password);112                         if((user.uid=mysql_check_login(user))>0)113                         {114                             printf("验证成功\n");115                         }116                         else117                         {118                             printf("验证失败\n");119                         }120                         send(clientfd,(char *)&user,sizeof(struct User),0);121                         break;122                     }123                 case FILE_PUSH:124                     {125                         char buffer[BUFFER_SIZE];126                         int data_len;127                         FILE * fp=NULL;128                         bzero(buffer,BUFFER_SIZE);129                         if((fp=fopen("data","wb"))==NULL)130                         {131                             perror("文件打开失败");132                             exit(-1);133                         }134                         //循环接收数据135                         int size=0;//表示有多少个块136                         while(data_len=recv(clientfd,buffer,BUFFER_SIZE,0))137                         {138                             if(data_len<0)139                             {140                                 perror("接收数据错误");141                                 exit(-1);142                             }143                             size++;144                             if(size==1)145                                 printf("正在接收来自%s:%d的文件\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));146                             else147                                 printf(".");148                             //向文件中写入149                             int write_len=fwrite(buffer,sizeof(char),data_len,fp);150                             if(write_len>data_len)151                             {152                                 perror("写入数据错误");153                                 exit(-1);154                             }155                             bzero(buffer,BUFFER_SIZE);156                         }157                         if(size>0)158                             printf("\n%s:%d的文件传送完毕\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));159                         else160                             printf("\n%s:%d的文件传送失败\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));161                         fclose(fp);162                         //rename("data","asdf");//这里可以修改文件的名字163                         exit(0);164                         break;165                     }166                 case FILE_PULL:167                     {168                         break;169                     }170                 case FILE_LIST:171                     {172                         break;173                     }174                 case FILE_DELECT:175                     {176                         break;177                     }178                 default:179                     {180                         break;181                     }182             }183             close(clientfd);//短连接结束184             exit(0);//退出子进程185         }186     }187 188     return 0;189 }190 191 192 //函数定义193 int mysql_check_login(struct User user)194 {195     MYSQL conn;196     MYSQL_RES *res_ptr;197     MYSQL_ROW result_row;198     int res;199     int row;200     int column;201     int uid;202     char sql[256]={0};203     strcpy(sql,"select uid from users where username=\"");204     strcat(sql,user.username);205     strcat(sql,"\" and password=\"");206     strcat(sql,user.password);207     strcat(sql,"\";");208     printf("查询的sql:%s\n",sql);209     uid=-1;210     mysql_init(&conn);211     if(mysql_real_connect(&conn,"localhost","root","","filetranslate",0,NULL,CLIENT_FOUND_ROWS))212     {213         res=mysql_query(&conn,sql);214         if(res)215         {216             perror("Select SQL ERROR!");217             exit(-1);218         }219         else220         {221             res_ptr=mysql_store_result(&conn);222             if(res_ptr)223             {224                 column=mysql_num_fields(res_ptr);//获取列数225                 row=mysql_num_rows(res_ptr)+1;//获取行数,加1表示还有第一行字段名226                 if(row<=1)227                 {228                     ;//验证失败229                 }230                 else231                 {232                     //这里先假定username是唯一233                     result_row=mysql_fetch_row(res_ptr);234                     printf("获取到的uid是:%s\n",result_row[0]);235                     uid=atoi(result_row[0]);236                 }237             }238             else239             {240                 printf("没有查询到匹配的数据\n");241             }242         }243     }244     else245     {246         perror("Connect Failed!\n");247         exit(-1);248     }249     mysql_close(&conn);250     return uid;251 }252 253 void print_time(char *ch)254 {255     time_t now;256     struct tm * stm;257     time(&now);258     stm=localtime(&now);259     sprintf(ch,"%02d:%02d:%02d\n",stm->tm_hour,stm->tm_min,stm->tm_sec);260     return ;261 }262 263 int MAX(int a,int b)264 {265     if(a>b)266         return a;267     return b;268 }
复制代码

  下面给张运行时的截图

 

  关于c语言调用mysql: http://www.cnblogs.com/wunaozai/p/3876134.html

  本文地址: http://www.cnblogs.com/wunaozai/p/3887728.html


原创粉丝点击