tcp/ip通信银行系统

客户端:

  1 //银行自助终端机
  2 //1.注册/登录
  3 //2.取钱/存钱/转账/查询
  4 #include<stdio.h>
  5 #include<string.h>
  6 #include<sys/types.h>
  7 #include<sys/socket.h>
  8 #include<netinet/in.h>
  9 #include<stdlib.h>
 10 #include<unistd.h>
 11 #include<arpa/inet.h>
 12 #include<time.h>
 13 
 14 typedef struct Head_bag//包头
 15 {
 16     int type;
 17     int bag_id;    
 18 }HB;
 19 
 20 typedef struct User
 21 {
 22     int type;
 23     int num;//银行系统编号
 24     int ret;
 25     char user_id[20];//身份证号
 26     char card_id[20];//银行卡号
 27     char des_card_id[20];//转账银行卡号
 28     char name[20];
 29     char sex[6]; 
 30     char phone[13];//电话号
 31     char regist_date[12];//注册日期
 32     char passwd[7];
 33     char mod_passwd[7];
 34     float balance;//余额
 35     float money;//余额
 36 }User;
 37 
 38 int ret = 0;
 39 
 40 void first_menu();
 41 void second_menu();
 42 int head_bag_init(HB *pbag);//初始化包
 43 void regist_info(User *puser);//输入个人信息
 44 void user_login(User *puser);//用户登录
 45 char *package_info(HB *pbag,User *puser,char *p);//数据打包
 46 void register_account(int sock,char *p,User *puser);//注册账户名
 47 void get_now_time(char *str,int len);//获取当前时间
 48 int judge_num_strlen(char *str,int len);//判断数字字符串长短是否符合要求
 49 void judge_input_user_id(User *puser);//判断身份证号
 50 void judge_input_phone(User *puser);//判断电话号
 51 void judge_input_passwd(User *puser);//判断密码
 52 void judge_input_card_id(User *puser);//判断银行账号
 53 void save_money(User *puser,int *sock);//存钱
 54 void draw_money(User *puser,int *sock);//取钱
 55 void transfer_accounts(User *puser,int *sock);//转账
 56 void find_balance(User *psuer,int *sock);//转账
 57 void modify_phone(User *puser,int *sock);//修改电话号码
 58 void modify_passwd(User *puser,int *sock);//修改密码
 59 void delete_card_id(User *puser,int *sock);//注销账户
 60 void print_receipt(User *puser);//打印凭条
 61 
 62 int main()
 63 {
 64     struct sockaddr_in server_addr;
 65     server_addr.sin_family = AF_INET;//通用族
 66     server_addr.sin_port = 4667;//端口号,随便起
 67     server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//服务器的ip
 68     
 69     int sock = 0;
 70     sock = socket(AF_INET,SOCK_STREAM,0);//创建通信套接字
 71     if(sock < 0)
 72     {
 73         perror("socket error\n");
 74         exit(-1);
 75     }
 76 
 77     ret = connect(sock,(struct sockaddr *)&server_addr,sizeof(struct sockaddr));//向服务器发送连接请求
 78     if(ret < 0)
 79     {
 80         perror("connect error\n");
 81         exit(-1);
 82     }
 83     while(1)
 84     {
 85         int len = 0;
 86         len = sizeof(struct sockaddr);
 87         
 88         HB *pbag = NULL;
 89         User *puser = NULL;
 90         HB bag;
 91         memset(&bag,0,sizeof(HB));
 92         pbag = &bag;
 93         User user;
 94         memset(&user,0,sizeof(User));
 95         puser = &user;
 96 
 97         first_menu();//登录/注册菜单
 98         int num = head_bag_init(pbag);//初始化
 99         
100         //注册/登录数据包
101         char *p = NULL;
102         p = (char *)malloc(sizeof(HB) + sizeof(User));
103         memset(p,0,sizeof(HB) + sizeof(User));//清空
104 
105 
106         if(num == 0)//返回主界面
107         {
108             p = package_info(pbag,puser,p);//个人信息数据打包
109  /*1*/            ret = send(sock,p,sizeof(HB)+sizeof(User),0);//向服务器发送客户端退出请求
110             if(ret < 0)
111             {
112                 perror("send error\n");
113                 exit(-1);
114             }
115             break;
116         }
117         else if(num == 1)//注册
118         {
119             regist_info(puser);//注册输入个人信息
120             p = package_info(pbag,puser,p);//个人信息数据打包
121         
122             register_account(sock,p,puser);//向服务器端发送用户信息从服务器端生成账户名返回到客户端
123         }
124         else if(num == 2)//登录
125         {
126             user_login(puser);//输入登录信息
127             p = package_info(pbag,puser,p);//数据打包
128 /*1*/          ret = send(sock,p,sizeof(HB)+sizeof(User),0);//向服务器发送登录信息
129             if(ret < 0)
130             {
131                 perror("send error :\n");
132                 exit(-1);
133             }
134 
135             int signal = 0;
136             ret = recv(sock,&signal,sizeof(int),0);//接受登录后的结果
137             if(ret < 0)
138             {
139                 perror("recv error :\n");
140                 exit(-1);
141             }
142 
143             if(signal == 1)//登录成功
144             {
145                 while(1)
146                 {
147                     second_menu();//登录成功后的操作
148 
149                     printf("输入你的操作:");
150                     scanf("%d",&puser->type);
151 
152                     if(puser->type == 0)//向服务器端发送退出请求
153                     {
154                         ret = send(sock,puser,sizeof(User),0);//向服务器发送客户端退出请求
155                         if(ret < 0)
156                         {
157                             perror("send error\n");
158                             exit(-1);
159                         }
160                         break;
161                     }
162                     switch(puser->type)
163                     {
164                         case 1://查询余额
165                             find_balance(puser,&sock);//转账
166                             print_receipt(puser);//打印凭条
167                             break;
168                         case 2://取钱
169                             draw_money(puser,&sock);//取钱
170                             print_receipt(puser);//打印凭条
171                             break;
172                         case 3://存钱
173                             save_money(puser,&sock);//存钱
174                             print_receipt(puser);//打印凭条
175                             break;
176                         case 4://转账
177                             transfer_accounts(puser,&sock);//转账
178                             print_receipt(puser);//打印凭条
179                             break;
180                         case 5://修改账户密码
181                             modify_passwd(puser,&sock);
182                             break;
183                         case 6://修改手机号
184                             modify_phone(puser,&sock);
185                             break;
186                         case 7://注销账户
187                             delete_card_id(puser,&sock);
188                             break;
189                     }
190                 }
191             }
192             else if(signal == 2)//密码错误
193             {
194                 printf("密码输入错误!\n");
195             }
196             else if(signal == 3)//账户名输入有误
197             {
198                 printf("账户名输入错误!\n");
199             }
200         }
201         else
202         {
203             printf("输入错误!\n");
204         }
205     }
206     close(sock);
207 
208     return 0;
209 }
210 
211 void first_menu()
212 {
213     char buf[30] = {0};
214     get_now_time(buf,sizeof(buf));
215     printf("**********************************************\n");
216     printf("*                                            *\n");
217     printf("*         注册====================1          *\n");
218     printf("*         登录====================2          *\n");
219     printf("*         退出====================0          *\n");
220     printf("*                                            *\n");
221     printf("**********************************************\n");
222     printf("\n");
223 }
224 
225 void second_menu()
226 {
227     char buf[30] = {0};
228     get_now_time(buf,sizeof(buf));
229     printf("**********************************************\n");
230     printf("*                                            *\n");
231     printf("*   查询余额=============================1   *\n");
232     printf("*   取钱业务=============================2   *\n");
233     printf("*   存钱业务=============================3   *\n");
234     printf("*   本行转账=============================4   *\n");
235     printf("*   修改账户密码=========================5   *\n");
236     printf("*   修改手机号===========================6   *\n");
237     printf("*   注销账户=============================7   *\n");
238     printf("*   退出=================================0   *\n");
239     printf("*                                            *\n");
240     printf("**********************************************\n");
241     printf("\n");
242 }
243 int head_bag_init(HB *pbag)//初始化包,登录/注册
244 {
245     printf("请输入你的操作:");
246     scanf("%d",&pbag->type);
247     return pbag->type;
248 }
249 void regist_info(User *puser)//输入个人信息
250 {
251     memset(puser,0,sizeof(User));//清空
252     printf("输入你的身份证号:");
253     
254     scanf("%s",puser->user_id);
255     judge_input_user_id(puser);//判断身份证号
256     printf("输入你的姓名:");
257     scanf("%s",puser->name);
258     printf("输入你的性别:");
259     scanf("%s",puser->sex);
260     if(strcmp(puser->sex,"man") != 0 && strcmp(puser->sex,"woman") != 0)
261     {
262         printf("请从新输入,性别:男(man),女(woman):");
263         scanf("%s",puser->sex);
264     }
265     printf("输入你的电话:");
266     scanf("%s",puser->phone);
267     judge_input_phone(puser);//判断电话号
268     printf("输入账户六位数密码:");
269     scanf("%s",puser->passwd);    
270     judge_input_passwd(puser);//判断密码
271 }
272 /*
273  *函数功能:发送用户信息从服务器生成账户名返回客户端
274  */
275 void register_account(int sock,char *p,User *puser)
276 {
277     ret = send(sock,p,sizeof(HB)+sizeof(User),0);//发送注册信息
278     if(ret < 0)
279     {
280         perror("send error\n");
281         exit(-1);
282     }
283     
284     ret = recv(sock,puser,sizeof(User),0);//接受注册后的账户
285     if(ret < 0)
286     {
287         perror("recv error\n");
288         exit(-1);
289     }
290     printf("注册成功!\n");
291     printf("记住你的银行账户为:%s\n",puser->card_id);
292 }
293 void user_login(User *puser)
294 {
295     memset(puser,0,sizeof(User));
296     printf("输入银行账号:");
297     scanf("%s",puser->card_id);
298     judge_input_card_id(puser);//判断银行账号
299     printf("输入账户密码:");
300     scanf("%s",puser->passwd);
301     judge_input_passwd(puser);//判断密码
302 }
303 
304 char *package_info(HB *pbag,User *puser,char *p)//信息数据打包
305 {
306     char *q = NULL;
307     memcpy(p,pbag,sizeof(HB));//将bag地址的内容放入p指向的空间
308     q = p + sizeof(HB);//p指针后移sizeof(HB)个大小
309     memcpy(q,puser,sizeof(User));//将用户信息放入进去
310     
311     return p;
312 }
313 /*
314  *函数功能:存钱
315  */
316 void save_money(User *puser,int *sock)
317 {
318     printf("输入你存入的金额:");
319     scanf("%f",&puser->money);
320     ret = send(*sock,puser,sizeof(User),0);//发送操作数信息
321     if(ret < 0)
322     {
323         perror("send error :\n");
324         exit(-1);
325     }
326 
327     ret = recv(*sock,puser,sizeof(User),0);
328     if(ret < 0)
329     {
330         perror("revc error :\n");
331         exit(-1);
332     }
333     printf("你的账户余额是%.1f\n",puser->balance);
334 }
335 /*
336  *函数功能:取钱
337  */
338 void draw_money(User *puser,int *sock)
339 {
340     printf("输入你要取的金额:");
341     scanf("%f",&puser->money);
342     ret = send(*sock,puser,sizeof(User),0);//发送操作数信息
343     if(ret < 0)
344     {
345         perror("send error :\n");
346         exit(-1);
347     }
348 
349     ret = recv(*sock,puser,sizeof(User),0);
350     if(ret < 0)
351     {
352         perror("revc error :\n");
353         exit(-1);
354     }
355     if(puser->balance == 0)
356     {
357         printf("你所取的金额超过余额!\n");
358     }
359     else
360     {
361         printf("你的账户余额是%.1f\n",puser->balance);
362     }
363 }
364 /*
365  *函数功能:转账
366  */
367 void transfer_accounts(User *puser,int *sock)
368 {
369     printf("输入你要转入的账户号:");
370     scanf("%s",puser->des_card_id);
371     judge_input_card_id(puser);//判断银行账号
372     printf("输入你要转账的金额:");
373     scanf("%f",&puser->money);
374     ret = send(*sock,puser,sizeof(User),0);//发送操作数信息
375     if(ret < 0)
376     {
377         perror("send error :\n");
378         exit(-1);
379     }
380 
381     ret = recv(*sock,puser,sizeof(User),0);
382     if(ret < 0)
383     {
384         perror("revc error :\n");
385         exit(-1);
386     }
387     if(puser->balance == 0)
388     {
389         printf("你转的金额超过余额!\n");
390     }
391     else
392     {
393         printf("你的账户余额是%.1f\n",puser->balance);
394     }
395 }
396 /*
397  *函数功能:查询余额
398  */
399 void find_balance(User *puser,int *sock)
400 {
401     ret = send(*sock,puser,sizeof(User),0);//发送操作数信息
402     if(ret < 0)
403     {
404         perror("send error :\n");
405         exit(-1);
406     }
407 
408     ret = recv(*sock,puser,sizeof(User),0);
409     if(ret < 0)
410     {
411         perror("revc error :\n");
412         exit(-1);
413     }
414     printf("你的账户余额是%.1f\n",puser->balance);
415 }
416 /*
417  *函数功能:修改账户密码
418  */
419 void modify_passwd(User *puser,int *sock)
420 {
421     printf("输入你要修改后的密码:");
422     scanf("%s",puser->mod_passwd);
423     judge_input_passwd(puser);//判断密码
424     ret = send(*sock,puser,sizeof(User),0);//发送操作数信息
425     if(ret < 0)
426     {
427         perror("send error :\n");
428         exit(-1);
429     }
430     ret = recv(*sock,puser,sizeof(User),0);
431     if(ret < 0)
432     {
433         perror("revc error :\n");
434         exit(-1);
435     }
436     printf("密码修改成功!\n");
437 }
438 /*
439  *函数功能:修改手机号
440  */
441 void modify_phone(User *puser,int *sock)
442 {
443     printf("输入修改后的电话号码:");
444     scanf("%s",puser->phone);
445     judge_input_phone(puser);//判断电话号
446     ret = send(*sock,puser,sizeof(User),0);//发送操作数信息
447     if(ret < 0)
448     {
449         perror("send error :\n");
450         exit(-1);
451     }
452 
453     ret = recv(*sock,puser,sizeof(User),0);
454     if(ret < 0)
455     {
456         perror("revc error :\n");
457         exit(-1);
458     }
459     printf("电话号码修改成功,请记住:%s!\n",puser->phone);
460 }
461 /*
462  *函数功能:注销账户
463  */
464 void delete_card_id(User *puser,int *sock)
465 {
466     ret = send(*sock,puser,sizeof(User),0);//发送操作数信息
467     if(ret < 0)
468     {
469         perror("send error :\n");
470         exit(-1);
471     }
472     ret = recv(*sock,puser,sizeof(User),0);
473     if(ret < 0)
474     {
475         perror("revc error :\n");
476         exit(-1);
477     }
478     if(puser->ret == 1)
479     {
480         printf("账户注销成功!\n");
481     }
482 }
483 /*
484  *函数功能:获取当前时间
485  */
486 void get_now_time(char *str,int len)
487 {
488     time_t timep;
489     struct tm *p = NULL;
490 
491     timep = time(NULL);
492     p = localtime(&timep);//取得1900年1月1日到现在的秒数
493     char format[] = {"%Y-%m-%d %A %H:%M:%S"};
494     strftime(str,len,format,p);
495 }
496 //判断是不是有数字组成,并且
497 int judge_num_strlen(char *str,int len) 
498 {
499     int i = 0;
500     while(str[i] != '\0')
501     {    
502         if(str[i] < '0' && str[i] > '9')//在0-9之外
503         {
504             return i;
505         }
506         i ++;
507     }
508     if(i == len)
509     {
510         return -1;   //长度符合,并且是数字
511     }else
512     {
513         return i;   
514     }
515 }
516 
517 void judge_input_user_id(User *puser)//判断身份证号
518 {     
519     int num =0;
520     num = judge_num_strlen(puser->user_id,18);
521     while(num != 0)
522     {
523         if(num == -1)//输入正确
524         {
525             break;
526         }else 
527         {
528             printf("输入只能是18位数字,请重输入:"); 
529             scanf("%s",puser->user_id);
530             num=0;
531             num = judge_num_strlen(puser->user_id,18);
532         }
533     }
534 }
535 void judge_input_phone(User *puser)//判断电话号
536 {
537     int num = 0;
538     num = judge_num_strlen(puser->phone,11);
539     while(num != 0)
540     {
541         if(num == -1)
542         {
543             break;
544         }
545         else
546         {
547             printf("只能是11位数字,请重输入:\n");
548             scanf("%s",puser->phone);
549             num=0;
550             num=judge_num_strlen(puser->phone,11);
551         }
552     }
553 }
554 void judge_input_passwd(User *puser)//判断密码
555 {
556     int num = 0;
557     num = judge_num_strlen(puser->passwd,6);
558     while(num != 0)
559     {
560         if(num == -1)
561         {
562             break;
563         }
564         else 
565         {
566             printf("输入只能是6位数字,请重输入");
567             scanf("%s",puser->passwd);
568             num = 0;
569             num = judge_num_strlen(puser->passwd,6);
570         }
571     }
572 }
573 void judge_input_card_id(User *puser)//判断银行账号
574 {
575     int num = 0;
576     num = judge_num_strlen(puser->card_id,16);
577     while(num != 0)
578     {
579         if(num == -1)
580         {
581             break;
582         }else
583         {
584             printf("输入只能是16位数字,请重输入:"); 
585             scanf("%s",puser->card_id);
586             num = 0;
587             num = judge_num_strlen(puser->card_id,16);
588         }
589     }
590 }
591 void print_receipt(User *puser)//打印凭条
592 {
593     char buf[30] = {0};
594     get_now_time(buf,sizeof(buf));
595     printf("\n");
596     printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
597     printf("\n");
598     printf("              交易凭条\n");
599     printf("  交易日期 : %s\n",buf);
600     printf("  银行账户 : %s\n",puser->card_id);
601     printf("  余额 : %.1f\n",puser->balance);
602     printf("\n");
603     printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
604     printf("\n");
605 }

服务端:

  1 //银行自助终端机
  2 //1.注册/登录
  3 //2.取钱/存钱/转账/查询
  4 
  5 #include<stdio.h>
  6 #include<string.h>
  7 #include<sys/types.h>
  8 #include<sys/socket.h>
  9 #include<netinet/in.h>
 10 #include<stdlib.h>
 11 #include<unistd.h>
 12 #include<arpa/inet.h>
 13 #include<semaphore.h>
 14 #include<pthread.h>
 15 #include<errno.h>
 16 #include<mysql/mysql.h>
 17 #include<time.h>
 18 #include<fcntl.h>
 19 
 20 #define PORT 4667//端口号
 21 #define SOCKNUM 10//监听的连接客户端数量
 22 
 23 typedef struct Head_bag//包头
 24 {
 25     int type;
 26     int bag_id;    
 27 }HB;
 28 
 29 typedef struct User
 30 {
 31     int type;
 32     int num;//银行系统编号
 33     int ret;
 34     char user_id[20];//身份证号
 35     char card_id[20];//银行卡号
 36     char des_card_id[20];//转账银行卡号
 37     char name[20];
 38     char sex[6]; 
 39     char phone[13];//电话号
 40     char regist_date[12];//注册日期
 41     char passwd[7];
 42     char mod_passwd[7];
 43     float balance;//余额
 44     float money;//取钱
 45 }User;
 46 
 47 struct node//队列
 48 {
 49     int sockfd;//监听套接字
 50     struct node *next;//指针域
 51 };
 52 
 53 int ret = 0;
 54 sem_t sem;//声明信号量
 55 
 56 void *fun(void *arg);
 57 void set_server(struct sockaddr_in server_addr,int *sock);//设置服务器
 58 void push_queue(struct node *queue,int sockfd);//入队
 59 int pop_queue(struct node *queue);//出队
 60 int is_empty(struct node *queue);//队列判空
 61 int login_mysql(char *p,User *puser);//登录银行账户
 62 char *packet_docode_user(char *p,User *puser);//解析数据包到用户信息
 63 void create_account(char *str);//生成银行账户
 64 void get_now_time(char *str,int len);//获取当前时间
 65 void link_mysql(MYSQL *pmysql,MYSQL *con);//连接数据库
 66 void send_sql_DBMS(MYSQL *pmysql,char *sql);//给数据库发送sql语言,通过DBMS执行
 67 void write_error_file(char *error_name);//将错误写入错误日志文件
 68 void write_info_mysql(User *puser);//将注册用户信息写入数据库
 69 void regist_bank_account(char *p,User *puser,int *sockfd);//注册银行账户
 70 void find_balance_mysql(User *puser,int *sockfd);//从数据库查询余额并返回
 71 void draw_money_mysql(User *puser,int *sockfd);//从数据库取钱
 72 void transfer_money_mysql(User *puser,int *sockfd);//从数据库转账
 73 void add_money_mysql(User *puser,int *sockfd);//从数据库存钱
 74 void modify_passwd_mysql(User *puser,int *sockfd);//从数据库修改密码并更新
 75 void modify_phone_mysql(User *puser,int *sockfd);//从数据库修改电话号码
 76 void delete_card_id_mysql(User *puser,int *sockfd);//从数据库删除银行账户
 77 void write_history_file(int options,User *puser);//创建账户文件将用户的操作信息放进日志文件中
 78 void write_handle(int fd,char *str,char *messag,int len,User *puser);//将用户的操作信息放进日志文件中
 79 
 80 //#include "head.h"
 81 
 82 int main()
 83 {    
 84     sem_init(&sem,0,0);//初始化信号量
 85     //定义一个队列
 86     struct node *queue = NULL;
 87     queue = (struct node *)malloc(sizeof(struct node));//申请一个动态空间
 88     memset(queue,0,sizeof(struct node));//清空
 89 
 90     //TCP服务器创建和设置
 91     struct sockaddr_in server_addr,client_addr;
 92     memset(&server_addr,0,sizeof(struct sockaddr_in));//清空
 93     memset(&client_addr,0,sizeof(struct sockaddr_in));//清空
 94 
 95     int sock = 0;
 96     
 97     set_server(server_addr,&sock);//设置服务器
 98     
 99     int sockfd = 0;//监听套接字
100     
101     //创建两个子线程
102     pthread_t thread[SOCKNUM] = {0};//声明线程id号
103     for(int i = 0;i < SOCKNUM;i ++)
104     {
105         ret = pthread_create(&thread[i],NULL,fun,(void *)queue);//创建线程
106         if(ret != 0)
107         {
108             write_error_file("pthread_create : ");
109             exit(-1);
110         }
111     }
112 
113     while(1)
114     {
115         int size = sizeof(struct sockaddr_in);
116 
117         sockfd = accept(sock,(struct sockaddr *)&client_addr,&size);//将接受到来自客户端的连接赋值给监听套接字
118         if(sockfd < 0)
119         {
120             write_error_file("accept : ");
121             exit(-1);
122         }
123        
124         push_queue(queue,sockfd);//客户套接字进入队列
125 
126         sem_post(&sem);//信号量增值
127     
128     }
129     close(sock);
130 
131     return 0;
132 }
133 
134 void *fun(void *arg)
135 {
136     struct node *queue = (struct node *)arg;//强转指针
137     
138     while(1)//服务器循环处理来自客户端的请求
139     {        
140         sem_wait(&sem);//信号量减值
141         int sockfd = pop_queue(queue);//出队的监听套接字
142         while(1)//循环读取套接字处理任务
143         {
144 
145             char *p = NULL;
146             p = (char *)malloc(sizeof(HB) + sizeof(User));//开辟动态空间
147             memset(p,0,sizeof(HB) + sizeof(User));
148 
149             HB *pbag = NULL;
150             User *puser = NULL;
151             
152             int len = 0;
153             len = sizeof(struct sockaddr);
154 
155             ret = recv(sockfd,p,sizeof(HB) + sizeof(User),0);//接受数据包,
156             if(ret < 0)
157             {
158                 write_error_file("recv: ");
159                 exit(-1);
160             }
161            
162             //取数据包type判断登录还是注册 
163             char *q = NULL;
164             q = p;
165             pbag = (HB *)q;//强转
166             
167             if(pbag->type == 0)//来自客户端监听套接字退出条件
168             {
169                 break;
170             }
171             else if(pbag->type == 1)//注册
172             {
173                 regist_bank_account(p,puser,&sockfd);//注册银行账户
174                 write_history_file(1,puser);
175             }
176             else if(pbag->type == 2)//进入服务器数据库进行相关操作修改
177             {
178                 int num = login_mysql(p,puser);//从数据库验证账户密码实现用户登录
179                 
180                 ret = send(sockfd,&num,sizeof(int),0);//发送登录是否成功的结果
181                 if(ret < 0)
182                 {
183                     write_error_file("recv");
184                     exit(-1);
185                 }
186                 
187                 p = p + sizeof(HB);//指针后移
188                 puser = (User *)p;
189                 
190                 while(1)//注销退出条件
191                 {
192                     ret = recv(sockfd,puser,sizeof(User),0);//接受登录成功后的选项,取,转,存
193                     if(ret < 0)
194                     {
195                         write_error_file("recv");
196                         exit(-1);
197                     }
198                     if(puser->type == 0)//来自监听客户端的退出条件
199                     {
200                         break;
201                     }
202               
203                     switch(puser->type)//登录成功后的选项,取,转,存
204                     {
205                         case 1://查询余额
206                             find_balance_mysql(puser,&sockfd);
207                             break;
208                         case 2://取钱
209                             draw_money_mysql(puser,&sockfd); 
210                             break;
211                         case 3://存钱
212                             add_money_mysql(puser,&sockfd);
213                             break;
214                         case 4://转账
215                             transfer_money_mysql(puser,&sockfd);
216                             break;
217                         case 5://修改账户密码
218                             modify_passwd_mysql(puser,&sockfd);
219                             break;
220                         case 6://修改手机号
221                             modify_phone_mysql(puser,&sockfd);
222                             break;
223                         case 7://注销账户
224                             delete_card_id_mysql(puser,&sockfd);
225                             break;
226                     }
227                 }
228             }
229             else//输入错误
230             {
231                 printf("输入错误!\n");
232             }
233         }
234         close(sockfd);
235     }
236 }
237 //函数功能:从数据库删除银行账号
238 void delete_card_id_mysql(User *puser,int *sockfd)
239 {
240     MYSQL mysql;
241     mysql_init(&mysql);//调用初始化函数
242     MYSQL *con = NULL;
243     
244     link_mysql(&mysql,con);//连接数据库
245     char sql[150] = {0};
246     sprintf(sql,"delete from user where card_id = '%s';",puser->card_id);
247     send_sql_DBMS(&mysql,sql);//发送sql给DBMS,DBMS执行sql语言
248     
249     mysql_close(&mysql);//关闭连接
250     
251     User psend;
252     memset(&psend,0,sizeof(User));
253 
254     memcpy(&psend,puser,sizeof(User));//将puser指向空间里的内容赋值给psend指向的空间
255 
256     ret = send(*sockfd,&psend,sizeof(User),0);
257     if(ret < 0)
258     {
259         write_error_file("send");
260         exit(-1);
261     }
262     write_history_file(8,&psend);                  
263 }
264 //函数功能:从数据库修改电话号码并更新数据库
265 void modify_phone_mysql(User *puser,int *sockfd)
266 {
267     MYSQL mysql;
268     mysql_init(&mysql);//调用初始化函数
269     MYSQL *con = NULL;
270     
271     link_mysql(&mysql,con);//连接数据库
272     char sql[150] = {0};//"select * from user";
273     
274     sprintf(sql,"select phone from user where card_id = '%s' and passwd ='%s'",puser->card_id,puser->passwd);
275     send_sql_DBMS(&mysql,sql);//发送sql给DBMS,DBMS执行sql语言
276     
277     MYSQL_RES *res = NULL;
278     MYSQL_ROW row;
279     memset(&row,0,sizeof(row));//清空
280    
281     res = mysql_store_result(&mysql);//获取查询结果集
282     row = mysql_fetch_row(res);//结果集中获取每一行
283        
284     memset(sql,0,sizeof(sql));
285     sprintf(sql,"update user set phone = %s where card_id = %s;",puser->phone,puser->card_id);
286 
287     send_sql_DBMS(&mysql,sql);//发送sql给DBMS,DBMS执行sql语言
288 
289     mysql_close(&mysql);//关闭连接
290     
291     User psend;
292     memset(&psend,0,sizeof(User));
293     
294     memcpy(&psend,puser,sizeof(User));//将puser指向空间里的内容赋值给psend指向的空间
295     printf("%s\n",puser->phone);
296     ret = send(*sockfd,&psend,sizeof(User),0);
297     if(ret < 0)
298     {
299         write_error_file("send");
300         exit(-1);
301     }
302     write_history_file(6,&psend);
303 }
304 //函数功能:从数据库修改密码并更新数据库
305 void modify_passwd_mysql(User *puser,int *sockfd)
306 {
307     MYSQL mysql;
308     mysql_init(&mysql);//调用初始化函数
309     MYSQL *con = NULL;
310     
311     link_mysql(&mysql,con);//连接数据库
312     char sql[150] = {0};//"select * from user";
313     
314     sprintf(sql,"select passwd from user where card_id = '%s';",puser->card_id);
315     send_sql_DBMS(&mysql,sql);//发送sql给DBMS,DBMS执行sql语言
316     
317     MYSQL_RES *res = NULL;
318     MYSQL_ROW row;
319     memset(&row,0,sizeof(row));//清空
320    
321     res = mysql_store_result(&mysql);//获取查询结果集
322     row = mysql_fetch_row(res);//结果集中获取每一行
323        
324     memset(sql,0,sizeof(sql));
325     sprintf(sql,"update user set passwd = %s where card_id = %s;",puser->mod_passwd,puser->card_id);
326 
327     send_sql_DBMS(&mysql,sql);//发送sql给DBMS,DBMS执行sql语言
328 
329     mysql_close(&mysql);//关闭连接
330     
331     User psend;
332     memset(&psend,0,sizeof(User));
333 
334     memcpy(&psend,puser,sizeof(User));//将puser指向空间里的内容赋值给psend指向的空间
335 
336     ret = send(*sockfd,&psend,sizeof(User),0);
337     if(ret < 0)
338     {
339         write_error_file("send");
340         exit(-1);
341     }
342     write_history_file(7,&psend);
343 }
344 
345 //函数功能:从数据库存钱
346 void add_money_mysql(User *puser,int *sockfd)
347 {
348     MYSQL mysql;
349     mysql_init(&mysql);//调用初始化函数
350     MYSQL *con = NULL;
351 
352     link_mysql(&mysql,con);//连接数据库
353     char sql[150]={0};// = "select * from user";
354     sprintf(sql,"select balance from user where card_id= '%s' and passwd = '%s'",puser->card_id,puser->passwd);
355     send_sql_DBMS(&mysql,sql);//发送sql给DBMS,DBMS执行sql语言
356     
357     MYSQL_RES *res = NULL;//结果集
358     MYSQL_ROW row;//行数集
359     memset(&row,0,sizeof(row));//清空
360    
361     res = mysql_store_result(&mysql);//获取查询结果集
362     row = mysql_fetch_row(res);//结果集中获取每一行
363     puser->balance = atof(row[0]) + puser->money;//取钱
364 
365     char str[150] = {0};
366     sprintf(str,"update user set balance = %f where card_id = %s;",puser->balance,puser->card_id);
367     send_sql_DBMS(&mysql,str);//发送sql给DBMS,DBMS执行sql语言
368     
369     mysql_close(&mysql);//关闭连接
370     printf("     %.1f\n",puser->balance);
371     User psend;
372     memset(&psend,0,sizeof(User));
373     
374     memcpy(&psend,puser,sizeof(User));//将puser指向空间里的内容赋值给psend指向的空间
375 
376     ret = send(*sockfd,&psend,sizeof(User),0);
377     if(ret < 0)
378     {
379         write_error_file("send find_balance : ");
380         exit(-1);
381     }
382     write_history_file(3,&psend);
383 }
384 //函数功能:从数据库中取钱
385 void draw_money_mysql(User *puser,int *sockfd)
386 {
387     MYSQL mysql;
388     mysql_init(&mysql);//调用初始化函数
389     MYSQL *con = NULL;
390     
391     link_mysql(&mysql,con);//连接数据库
392     char sql[150]={0};// = "select * from user";
393     sprintf(sql,"select balance from user where card_id= '%s' and passwd='%s'",puser->card_id,puser->passwd);
394     send_sql_DBMS(&mysql,sql);//发送sql给DBMS,DBMS执行sql语言
395     
396     MYSQL_RES *res = NULL;//结果集
397     MYSQL_ROW row;//行数集
398     memset(&row,0,sizeof(row));//清空
399    
400     res = mysql_store_result(&mysql);//获取查询结果集
401     row = mysql_fetch_row(res);//结果集中获取每一行
402 
403     puser->balance = atof(row[0]) - puser->money;//取钱
404     
405     if(puser < 0)//取得钱数为负数时余额不足
406     {
407         puser->balance = 0;
408     }
409     else
410     {
411         char str[150] = {0};
412         sprintf(str,"update user set balance = %f where card_id = %s;",puser->balance,puser->card_id);
413         send_sql_DBMS(&mysql,str);//发送sql给DBMS,DBMS执行sql语言
414     }
415     
416     mysql_close(&mysql);//关闭连接
417 
418     User psend;
419     memset(&psend,0,sizeof(User));
420 
421     memcpy(&psend,puser,sizeof(User));//将puser指向空间里的内容赋值给psend指向的空间
422 
423     ret = send(*sockfd,&psend,sizeof(User),0);
424     if(ret < 0)
425     {
426         perror("send");
427         write_error_file("send");
428         exit(-1);
429     }
430     write_history_file(4,&psend);                
431 }
432 //函数功能:从数据库查询余额
433 void find_balance_mysql(User *puser,int *sockfd)
434 {
435     MYSQL mysql;
436     mysql_init(&mysql);//调用初始化函数
437     MYSQL *con = NULL;
438     
439     link_mysql(&mysql,con);//连接数据库
440     char sql[50] = "select * from user";
441     send_sql_DBMS(&mysql,sql);//发送sql给DBMS,DBMS执行sql语言
442     
443     MYSQL_RES *res = NULL;
444     MYSQL_ROW row;
445     memset(&row,0,sizeof(row));//清空
446    
447 
448     res = mysql_store_result(&mysql);//获取查询结果集
449     for(int r = 0;r < mysql_num_rows(res);r ++)//mysql_num_rows(res)是行数
450     {
451         row = mysql_fetch_row(res);//结果集中获取每一行
452         if(row < 0)
453         {
454             break;
455         }
456         if(strcmp(puser->card_id,row[2]) == 0)
457         {
458             puser->balance = atof(row[8]);
459             break;
460         }
461     }
462     mysql_close(&mysql);//关闭连接
463     
464     //printf("%.1f\n",puser->balance);   
465     ret = send(*sockfd,puser,sizeof(User),0);
466     if(ret < 0)
467     {
468         write_error_file("send");
469         exit(-1);
470     }
471 }
472 //函数功能:从数据库转账
473 void transfer_money_mysql(User *puser,int *sockfd)
474 {
475     MYSQL mysql;
476     mysql_init(&mysql);//调用初始化函数
477     MYSQL *con = NULL;
478     
479     link_mysql(&mysql,con);//连接数据库
480 
481     char sql[150] = {0};//"select * from user";
482     sprintf(sql,"select balance from user where card_id= '%s' and passwd='%s'",puser->card_id,puser->passwd);//给自己发,查找自己的信息
483     send_sql_DBMS(&mysql,sql);//发送sql给DBMS,DBMS执行sql语言
484     
485     MYSQL_RES *res1 = NULL;//结果集
486     MYSQL_ROW row1;//行数集
487     memset(&row1,0,sizeof(row1));//清空
488    
489     res1 = mysql_store_result(&mysql);//获取查询结果集
490     row1 = mysql_fetch_row(res1);//结果集中获取每一行
491     
492     float  balance = puser->money;
493     puser->balance = atof(row1[0]) - puser->money;//转钱
494     
495     if(puser->balance < 0)//转的钱数为负数时余额不足
496     {
497         puser->balance = 0;
498     }
499     else
500     {
501         char str[150] = {0};
502         sprintf(str,"update user set balance = %f where card_id = %s;",puser->balance,puser->card_id);
503         send_sql_DBMS(&mysql,str);//发送sql给DBMS,DBMS执行sql语言
504         
505         memset(sql,0,sizeof(sql));
506         sprintf(sql,"select balance from user where card_id = '%s';",puser->des_card_id);//转账目标账号是否存在
507         send_sql_DBMS(&mysql,sql);//发送sql给DBMS,DBMS执行sql语言
508         MYSQL_RES *res = NULL;//结果集
509         MYSQL_ROW row;//行数集
510         memset(&row,0,sizeof(row));//清空
511         res = mysql_store_result(&mysql);//获取查询结果集
512         row = mysql_fetch_row(res);//结果集中获取每一行
513     
514         float fbalance = 0;
515         fbalance = atof(row[0]) + balance;
516         memset(sql,0,sizeof(sql));
517         sprintf(str,"update user set balance = %f where card_id = %s;",fbalance,puser->des_card_id);
518         send_sql_DBMS(&mysql,str);//发送sql给DBMS,DBMS执行sql语言
519     }
520     
521     mysql_close(&mysql);//关闭连接
522 
523     User psend;
524     memset(&psend,0,sizeof(User));
525 
526     memcpy(&psend,puser,sizeof(User));//将puser指向空间里的内容赋值给psend指向的空间
527 
528     ret = send(*sockfd,&psend,sizeof(User),0);
529     if(ret < 0)
530     {
531         write_error_file("send");
532         exit(-1);
533     }
534     write_history_file(5,&psend);
535 }
536 //函数功能:产生银行账户
537 void create_account(char *str)
538 {
539     memset(str,0,sizeof(char));
540     srand((unsigned)time(NULL));//获取随机数种子
541     int num = rand()%100000001;//产生0-到100000000的随机数
542     sprintf(str,"72256666%d",num);
543     str ++;
544 }
545 //函数功能:将注册用户信息写入数据库
546 void write_info_mysql(User *puser)
547 {
548     MYSQL mysql;
549     mysql_init(&mysql);//调用初始化函数
550     MYSQL *con = NULL;
551     
552     link_mysql(&mysql,con);//连接数据库
553     
554     //将注册用户信息写入数据库
555     char sql[400] = {0};
556     char date[20] = {0};
557     get_now_time(date,sizeof(date));//获取当前时间到数组
558 
559     strncpy(puser->regist_date,date,10);
560     puser->balance = 0;//初始化余额为0元
561     
562     sprintf(sql,"insert into user values(%d,'%s','%s','%s','%s','%s','%s','%s',%f)",puser->num ++,puser->user_id,puser->card_id,puser->name,puser->sex,puser->phone,puser->regist_date,puser->passwd,puser->balance);
563     
564     send_sql_DBMS(&mysql,sql);//发送sql给DBMS,DBMS执行sql语言
565     
566     mysql_close(&mysql);//关闭连接
567 }
568 //函数功能:注册银行账户
569 
570 void regist_bank_account(char *p,User *puser,int *sockfd)
571 {
572     p = p + sizeof(HB);
573     puser = (User *)p;
574 
575     create_account(puser->card_id);//生成银行账户
576     
577     ret = send(*sockfd,puser,sizeof(User),0);//发送卡号给客户端
578     if(ret < 0)
579     {
580         write_error_file("send");
581         exit(-1);
582     }
583     write_info_mysql(puser);//将注册信息写入数据库
584 }
585 //函数功能:连接数据库
586 void link_mysql(MYSQL *pmysql,MYSQL *con)
587 {
588     con = mysql_real_connect(pmysql,"localhost","root","123","bank",0,NULL,0);//连接数据库
589     if(con == NULL)
590     {
591         write_error_file((char *)mysql_error(pmysql));
592         exit(-1);
593     }
594 }
595 //函数功能:给数据库发送sql语言,通过DBMS执行
596 void send_sql_DBMS(MYSQL *pmysql,char *sql)
597 {
598     if(mysql_query(pmysql,sql) != 0)////发送sql给DBMS,DBMS执行sql语言
599     {
600         write_error_file((char *)mysql_error(pmysql));
601         exit(-1);
602     }
603 }
604 /*
605  *函数功能:从数据库下载数据和来自客户端的数据匹配
606  *返回值:登录成功返回1,密码错误返回2,,账户名错误返回3
607  */
608 int login_mysql(char *p,User *puser)
609 {
610     MYSQL mysql;//声明一个MYSQL结构体类型的mysql
611     MYSQL *con = NULL;
612     mysql_init(&mysql);//调用初始化函数
613 
614     link_mysql(&mysql,con);//连接数据库
615 
616     char sql[150] = "select * from user";
617 
618     send_sql_DBMS(&mysql,sql);//发送sql给DBMS,DBMS执行sql语言
619 
620     MYSQL_RES *res = NULL;
621     MYSQL_ROW row;
622     memset(&row,0,sizeof(row));//清空
623     
624     p = p + sizeof(HB);//指针后移
625     puser = (User *)p;
626     res = mysql_store_result(&mysql);//获取查询结果集
627     for(int r = 0;r < mysql_num_rows(res);r ++)//mysql_num_rows(res)是行数
628     {
629         row = mysql_fetch_row(res);//结果集中获取每一行
630         if(row < 0)
631         {
632             break;
633         }
634 
635         //printf("%s\t%s\n",puser->card_id,puser->passwd);    
636         if(strcmp(row[2],puser->card_id) == 0)//通过账号匹配
637         {
638             if(strcmp(row[7],puser->passwd)  == 0)//登陆成功
639             {
640                 mysql_free_result(res);//释放
641                 mysql_close(&mysql);//退出数据库
642                 write_history_file(4,puser);                
643                 return 1;
644 
645             }
646             else//密码错误
647             {
648                 return 2;
649             }
650         }
651         else//账户名错误
652         {
653             return 3;
654         }
655         mysql_free_result(res);//释放
656     }   
657     mysql_close(&mysql);//退出数据库
658 }
659 //入队
660 void push_queue(struct node *queue,int sockfd)
661 {
662     struct node *phead = queue;
663     struct node *new = (struct node *)malloc(sizeof(struct node));//申请动态空间
664     memset(new,0,sizeof(struct node));//清空
665     new->sockfd = sockfd;
666 
667     while((phead->next) != NULL)//判断链表是否为空
668     {
669         phead->next = phead;//指向下一个结点
670     }
671     phead->next = new;
672     new->next = NULL;
673 }
674 //出队
675 int pop_queue(struct node *queue)
676 {
677     int sockfd = 0;
678     struct node *phead = NULL;
679     phead = queue->next;//将第一个结点的指针域赋值给phead
680     sockfd = phead->sockfd;
681     queue->next = phead->next;
682     free(phead);
683 
684     return sockfd;
685 }
686 //判断队列是否为空
687 int is_empty(struct node *queue)
688 {
689     struct node *phead = queue->next;
690     if(phead == NULL)
691     {
692         return 1;
693     }
694     else
695     {
696         return 0;
697     }
698 }
699 //函数功能:获取当前时间,写入数组
700 void get_now_time(char *str,int len)
701 {
702     time_t timep;
703     struct tm *p = NULL;
704 
705     timep = time(NULL);
706     p = localtime(&timep);//取得1900年1月1日到现在的秒数
707     char format[] = {"%Y-%m-%d %A %H:%M:%S"};//格式化
708     strftime(str,len,format,p);
709 }
710 //函数功能:将服务器错误报告写入错误日志文件中
711 
712 void write_error_file(char *error_name)
713 {
714     int fd = 0;
715     char err[300] = {0};
716     get_now_time(err,sizeof(err));
717     strcat(err," : ");//字符串连接
718     strcat(err,strerror(errno));//将错误连到时间后
719     strcat(err,"\n");
720     fd = open("/home/zzk/桌面/项目/error_file.txt",O_RDWR | O_APPEND,644);//O_APPEND是每次操作操作都写入文件的末尾
721     if(fd < 0)
722     {
723         perror("open\n");
724         exit(-1);
725     }
726     if(write(fd,err,strlen(err)) == -1)
727     {
728         perror("write\n");
729         exit(-1);
730     }
731     close(fd);
732 }
733 
734  //函数功能:设置服务器,创建套接字绑定并等待连接请求
735 
736 void set_server(struct sockaddr_in server_addr,int *sock)
737 {
738     server_addr.sin_family = AF_INET;//指定的通用家族地址
739     server_addr.sin_port = PORT;//端口号,随便起
740     server_addr.sin_addr.s_addr = INADDR_ANY;//inet_addr("192.168.31.146");//服务器的ip
741     
742     *sock = socket(AF_INET,SOCK_STREAM,0);//创建TCP通信套接字 
743     if(sock < 0)
744     {
745         write_error_file("socket : ");
746         exit(-1);
747     }
748     ret = bind(*sock,(struct sockaddr *)&server_addr,sizeof(struct sockaddr));//将服务器自己的地址信息和通信套接字绑定
749     if(ret < 0)
750     {
751         write_error_file("bind");
752         exit(-1);
753     }
754     
755     ret = listen(*sock,SOCKNUM);//等待连接请求,SOCKNUM是客户端最大运行数
756     if(ret < 0)
757     {
758         write_error_file("listen");
759         exit(-1);
760     }
761 }
762 /*
763  *函数功能:将用户的操作信息写进日志文件中
764  * */
765 void write_handle(int fd,char *str,char *messag,int len,User *puser)
766 {
767         memset(str,0,len);//清空
768         get_now_time(str,sizeof(str));//获取当前时间
769         strcat(str,"  ");
770         strcat(str,puser->user_id);
771         strcat(str,messag);
772         strcat(str,"\n");
773         if(write(fd,str,strlen(str))==-1)//写入文件
774          {
775             write_error_file("write:");
776             exit(-1);
777         }
778         close(fd);//关闭文件
779 }
780 /*
781  *函数功能:将用户的操作信息放进日志文件中
782  *参数:options 客户进行操作项目的编码(1 注册,2 登录)
783  *返回值:无返回值
784  * */
785 void write_history_file(int options,User *puser)
786 {
787     int fd = 0;
788     char buf[128] = {0};
789     char str[128] = {0};
790     char message[50] = {0};
791     //get_now_time(str,sizeof(str));//获取当前时间
792     strcpy(buf,"home/zzk/桌面/项目/");
793     strcpy(buf,puser->user_id);
794     strcat(buf,".txt");//buf是文件名
795     fd = open(buf,O_WRONLY | O_CREAT | O_APPEND,0644);//打开一个并创建只写,或创建,追加的文件
796     if(fd < 0)
797     {
798         write_error_file("open : ");
799         exit(-1);
800     }
801     switch(options)
802     {
803         case 1://开户
804             strcpy(message,"成功的进行开户");
805             write_handle(fd,str,message,sizeof(str),puser);
806             break; 
807         case 2://登录
808             strcpy(message,"登录");
809             write_handle(fd,str,message,sizeof(str),puser);
810             break; 
811         case 3://存钱
812             sprintf(message,"存入%f元",puser->money);//写入缓冲取
813             write_handle(fd,str,message,sizeof(str),puser);
814             break; 
815         case 4://取钱
816             sprintf(message,"支出%f元",puser->money);//写入缓冲取
817             write_handle(fd,str,message,sizeof(str),puser);
818             break; 
819         case 5://转账
820             sprintf(message,"向%s转入%f元",puser->des_card_id,puser->money);//写入缓冲取
821             write_handle(fd,str,message,sizeof(str),puser);
822             break; 
823         case 6://修改手机号
824             sprintf(message,"修改后的预留手机号码:%s",puser->phone);//写入缓冲取
825             write_handle(fd,str,message,sizeof(str),puser);
826             break; 
827         case 7://修改账户密码
828             strcpy(message,"修改了账户密码");
829             write_handle(fd,str,message,sizeof(str),puser);
830             break; 
831         case 8://注销账户
832             strcpy(message,"注销了账户");
833             write_handle(fd,str,message,sizeof(str),puser);
834             break;                                         
835     }   
836 } 

 

posted @ 2021-03-06 18:04  天哥的小屋  阅读(354)  评论(0)    收藏  举报