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


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

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

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

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

      (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 user
    2 (
    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("验证登陆成功
    ");
     70     while(1)
     71     {
     72         printf("
    请输入操作指令:");
     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             else
    103             {
    104                 printf("该命令不支持
    ");
    105             }
    106         }
    107         else
    108         {
    109             printf("该命令不支持
    ");
    110         }
    111     }
    112 
    113 
    114     return 0;
    115 }
    116 
    117 //验证成功时返回大于0的uid号码,错误返回-1
    118 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
    ",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("传输完毕
    ");
    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
    ",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 
    ",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),clientfd);
     92         print_time(ch);
     93         printf("加入的时间是:%s
    ",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
    ",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
    ",user.username,user.password);
    112                         if((user.uid=mysql_check_login(user))>0)
    113                         {
    114                             printf("验证成功
    ");
    115                         }
    116                         else
    117                         {
    118                             printf("验证失败
    ");
    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的文件
    ",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
    146                             else
    147                                 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("
    %s:%d的文件传送完毕
    ",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
    159                         else
    160                             printf("
    %s:%d的文件传送失败
    ",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
    ",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         else
    220         {
    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                 else
    231                 {
    232                     //这里先假定username是唯一
    233                     result_row=mysql_fetch_row(res_ptr);
    234                     printf("获取到的uid是:%s
    ",result_row[0]);
    235                     uid=atoi(result_row[0]);
    236                 }
    237             }
    238             else
    239             {
    240                 printf("没有查询到匹配的数据
    ");
    241             }
    242         }
    243     }
    244     else
    245     {
    246         perror("Connect Failed!
    ");
    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
    ",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

  • 相关阅读:
    redux核心知识
    react性能优化要点
    react-router4的使用备注
    selenium启动Chrome配置参数问题
    Navicat15最新版本破解和破解报错总结
    Silence主题美化-部署
    vscode打开文件,中文显示乱码(已解决)
    Windows下Charles从下载安装到证书设置和浏览器抓包
    python下的selenium和chrome driver的安装
    Python 直接赋值、浅拷贝和深度拷贝解析
  • 原文地址:https://www.cnblogs.com/wunaozai/p/3887728.html
Copyright © 2020-2023  润新知