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 }